diff --git a/MAINTAINERS b/MAINTAINERS index 8287b2ba3ba6..f3486fa39b20 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14409,3 +14409,7 @@ AMLOGIC ADD LCD_EXTERN TL050FHV02CT DRIVER M: Weiming Liu F: drivers/amlogic/media/vout/lcd/lcd_extern/mipi_TL050FHV02CT.c +AMLOGIC ATV DEMOD DRIVER +M: nengwen.chen +F: drivers/amlogic/atv_demod/* +F: include/linux/amlogic/aml_atvdemod.h diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts index 4b1c34bc994d..b84ab002b722 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962e_r321.dts @@ -590,16 +590,20 @@ interrupt-names = "mailbox_2"; }; - aml_atv_demod { - compatible = "amlogic, aml_atv_demod"; - dev_name = "aml_atv_demod"; - status = "disabled"; + aml_atvdemod { + compatible = "amlogic, aml_atvdemod"; + dev_name = "aml_atvdemod"; + status = "okay"; + tuner = "si2151_tuner"; + tuner_i2c_ada_id = <&i2c1>; + tuner_i2c_addr = <0x60>; + btsc_sap_mode = <1>; ////pinctrl-names="atvdemod_agc"; ////pinctrl-0=<&atvdemod_agc>; reg = <0x0 0xff640000 0x0 0x2000 - 0x0 0xff648000 0x0 0x2000>; - /* default:0x88188832;r840 on haier:0x48188832 */ + 0x0 0xff648000 0x0 0x2000>; reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ }; bt-dev { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts index 0423db5cbad4..d44afb446ab5 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_1g.dts @@ -583,16 +583,20 @@ interrupt-names = "mailbox_2"; }; - aml_atv_demod { - compatible = "amlogic, aml_atv_demod"; - dev_name = "aml_atv_demod"; - status = "disabled"; + aml_atvdemod { + compatible = "amlogic, aml_atvdemod"; + dev_name = "aml_atvdemod"; + status = "okay"; + tuner = "mxl661_tuner"; + tuner_i2c_ada_id = <&i2c1>; + tuner_i2c_addr = <0x60>; + btsc_sap_mode = <1>; ////pinctrl-names="atvdemod_agc"; ////pinctrl-0=<&atvdemod_agc>; reg = <0x0 0xff640000 0x0 0x2000 - 0x0 0xff648000 0x0 0x2000>; - /* default:0x88188832;r840 on haier:0x48188832 */ + 0x0 0xff648000 0x0 0x2000>; reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ }; bt-dev { @@ -1380,6 +1384,13 @@ }; }; +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_dv_pins>; +}; + &pinctrl_periphs { /*i2s*/ aml_audio_i2s: aml_audio_i2s { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts index 451dd09bb4a6..f081609c21c3 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_2g.dts @@ -592,16 +592,20 @@ interrupt-names = "mailbox_2"; }; - aml_atv_demod { - compatible = "amlogic, aml_atv_demod"; - dev_name = "aml_atv_demod"; - status = "disabled"; + aml_atvdemod { + compatible = "amlogic, aml_atvdemod"; + dev_name = "aml_atvdemod"; + status = "okay"; + tuner = "mxl661_tuner"; + tuner_i2c_ada_id = <&i2c1>; + tuner_i2c_addr = <0x60>; + btsc_sap_mode = <1>; ////pinctrl-names="atvdemod_agc"; ////pinctrl-0=<&atvdemod_agc>; reg = <0x0 0xff640000 0x0 0x2000 - 0x0 0xff648000 0x0 0x2000>; - /* default:0x88188832;r840 on haier:0x48188832 */ + 0x0 0xff648000 0x0 0x2000>; reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ }; bt-dev { @@ -1389,6 +1393,13 @@ }; }; +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_dv_pins>; +}; + &pinctrl_periphs { /*i2s*/ aml_audio_i2s: aml_audio_i2s { diff --git a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts index ee6099da6a82..64089a8d00e9 100644 --- a/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts +++ b/arch/arm64/boot/dts/amlogic/txlx_t962x_r311_720p.dts @@ -591,16 +591,20 @@ interrupt-names = "mailbox_2"; }; - aml_atv_demod { - compatible = "amlogic, aml_atv_demod"; - dev_name = "aml_atv_demod"; - status = "disabled"; + aml_atvdemod { + compatible = "amlogic, aml_atvdemod"; + dev_name = "aml_atvdemod"; + status = "okay"; + tuner = "mxl661_tuner"; + tuner_i2c_ada_id = <&i2c1>; + tuner_i2c_addr = <0x60>; + btsc_sap_mode = <1>; ////pinctrl-names="atvdemod_agc"; ////pinctrl-0=<&atvdemod_agc>; reg = <0x0 0xff640000 0x0 0x2000 - 0x0 0xff648000 0x0 0x2000>; - /* default:0x88188832;r840 on haier:0x48188832 */ + 0x0 0xff648000 0x0 0x2000>; reg_23cf = <0x88188832>; + /*default:0x88188832;r840 on haier:0x48188832*/ }; bt-dev { @@ -1388,6 +1392,13 @@ }; }; +&i2c1 { + status = "okay"; + clock-frequency = <300000>; + pinctrl-names="default"; + pinctrl-0=<&i2c1_dv_pins>; +}; + &pinctrl_periphs { /*i2s*/ aml_audio_i2s: aml_audio_i2s { diff --git a/arch/arm64/configs/meson64_defconfig b/arch/arm64/configs/meson64_defconfig index ab18d7e27c23..dcf38837b05d 100644 --- a/arch/arm64/configs/meson64_defconfig +++ b/arch/arm64/configs/meson64_defconfig @@ -346,6 +346,7 @@ CONFIG_AMLOGIC_DDR_TOOL=y CONFIG_AMLOGIC_DDR_BANDWIDTH=y CONFIG_AMLOGIC_TEE=y CONFIG_AMLOGIC_GPIO_IRQ=y +CONFIG_AMLOGIC_ATV_DEMOD=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y diff --git a/drivers/amlogic/Kconfig b/drivers/amlogic/Kconfig index 329b208e4b9e..01a6155d65d5 100644 --- a/drivers/amlogic/Kconfig +++ b/drivers/amlogic/Kconfig @@ -125,5 +125,8 @@ source "drivers/amlogic/ledring/Kconfig" source "drivers/amlogic/memory_ext/Kconfig" source "drivers/amlogic/irqchip/Kconfig" + +source "drivers/amlogic/atv_demod/Kconfig" + endmenu endif diff --git a/drivers/amlogic/Makefile b/drivers/amlogic/Makefile index 77bea31e32f5..197924412fb1 100644 --- a/drivers/amlogic/Makefile +++ b/drivers/amlogic/Makefile @@ -116,3 +116,5 @@ obj-$(CONFIG_AMLOGIC_MEMORY_EXTEND) += memory_ext/ obj-$(CONFIG_AMLOGIC_LEDRING) += ledring/ obj-$(CONFIG_AMLOGIC_GPIO_IRQ) += irqchip/ + +obj-$(CONFIG_AMLOGIC_ATV_DEMOD) += atv_demod/ diff --git a/drivers/amlogic/atv_demod/Kconfig b/drivers/amlogic/atv_demod/Kconfig new file mode 100644 index 000000000000..be353f5f093e --- /dev/null +++ b/drivers/amlogic/atv_demod/Kconfig @@ -0,0 +1,17 @@ +# +# ATV driver configuration +# + +menu "Amlogic ATV driver" + +config AMLOGIC_ATV_DEMOD + tristate "Amlogic ATVDEMOD device driver" + default n + help + ATVDEMOD device driver. + Y: enable + N: disable + M: build as module + +endmenu + diff --git a/drivers/amlogic/atv_demod/Makefile b/drivers/amlogic/atv_demod/Makefile new file mode 100644 index 000000000000..52abf31f204d --- /dev/null +++ b/drivers/amlogic/atv_demod/Makefile @@ -0,0 +1,32 @@ +obj-$(CONFIG_AMLOGIC_ATV_DEMOD) += aml_atvdemod.o + +aml_atvdemod-objs = atvdemod_func.o atvauddemod_func.o atv_demod_v4l2.o atv_demod_driver.o atv_demod_ops.o + +ccflags-y += -I. +ccflags-y += -Idrivers/media/dvb-core +#ccflags-y += -Idrivers/amlogic/tuners/mxl661 +#ccflags-y += -Idrivers/amlogic/tuners/si2151 + +#obj-m += aml_atvdemod.o +# +#aml_atvdemod-objs = atvdemod_func.o atvauddemod_func.o +# +#aml_atvdemod-objs += atv_demod_v4l2.o atv_demod_driver.o atv_demod_ops.o +# +#ccflags-y += -I. +#ccflags-y += -Idrivers/media/dvb-core +# +#TARGET_PRODUCT=t962e_r321 +#KERNEL_ARCH=arm64 +#CROSS_COMPILE=aarch64-linux-gnu- +#PRODUCT_OUT=../../../../out/target/product/$(TARGET_PRODUCT)/obj/KERNEL_OBJ +# +#KBUILD_EXTRA_SYMBOLS += $(shell pwd)/../tuner/si2151_4.9/Module.symvers +# +#export KBUILD_EXTRA_SYMBOLS +# +#all: +# $(MAKE) -C $(PRODUCT_OUT) M=$(shell pwd) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules +# +#clean: +# rm -rf *.ko .*.ko.cmd *.o *.order *.symvers -f *.cmd .*.o.cmd *.mod.c .tmp_versions/ \ No newline at end of file diff --git a/drivers/amlogic/atv_demod/atv_demod_debug.h b/drivers/amlogic/atv_demod/atv_demod_debug.h new file mode 100644 index 000000000000..4d8e587da5c0 --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_debug.h @@ -0,0 +1,40 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ATV_DEMOD_DEBUG_H__ +#define __ATV_DEMOD_DEBUG_H__ + +extern int atvdemod_debug_en; + +#undef pr_info +#define pr_info(args...)\ + do {\ + if (atvdemod_debug_en)\ + printk(args);\ + } while (0) + +#undef pr_dbg +#define pr_dbg(args...) \ + do {\ + if (atvdemod_debug_en == 2)\ + printk(args);\ + } while (0) + +#undef pr_err +#define pr_err(args...) \ + do {\ + if (1)\ + printk(args);\ + } while (0) + +#endif /* __ATV_DEMOD_DEBUG_H__ */ diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.c b/drivers/amlogic/atv_demod/atv_demod_driver.c new file mode 100644 index 000000000000..43f52e02f20d --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_driver.c @@ -0,0 +1,598 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define ATVDEMOD_DEVICE_NAME "aml_atvdemod" +#define ATVDEMOD_DRIVER_NAME "aml_atvdemod" +#define ATVDEMOD_MODULE_NAME "aml_atvdemod" +#define ATVDEMOD_CLASS_NAME "aml_atvdemod" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drivers/media/dvb-core/dvb_frontend.h" + +#include "atv_demod_debug.h" +#include "atv_demod_driver.h" +#include "atv_demod_v4l2.h" +#include "atv_demod_ops.h" + +#include "atvdemod_func.h" +#include "atvauddemod_func.h" + + +#define AMLATVDEMOD_VER "Ref.2015/09/01a" + +struct aml_atvdemod_device *amlatvdemod_devp; + +static ssize_t aml_atvdemod_store(struct class *class, + struct class_attribute *attr, const char *buf, size_t count) +{ + int n = 0; + unsigned int ret = 0; + char *buf_orig = NULL, *ps = NULL, *token = NULL; + char *parm[4] = { NULL }; + unsigned int data_snr[128] = { 0 }; + unsigned int data_snr_avg = 0; + int data_afc = 0, block_addr = 0, block_reg = 0, block_val = 0; + int i = 0, val = 0; + unsigned long tmp = 0; + struct aml_atvdemod_device *aml_atvdemod_dev = NULL; + + aml_atvdemod_dev = container_of(class, struct aml_atvdemod_device, cls); + + buf_orig = kstrdup(buf, GFP_KERNEL); + ps = buf_orig; + + while (1) { + token = strsep(&ps, "\n "); + if (token == NULL) + break; + if (*token == '\0') + continue; + parm[n++] = token; + } + + if (!strncmp(parm[0], "init", strlen("init"))) { + ret = atv_demod_enter_mode(); + if (ret) + pr_info("[tuner..] atv_restart error.\n"); + } else if (!strncmp(parm[0], "audout_mode", strlen("audout_mode"))) { + if (get_atvdemod_state() == ATVDEMOD_STATE_WORK) { + if (is_meson_txlx_cpu()) { + atvauddemod_set_outputmode(); + pr_info("[tuner..] atvauddemod_set_outputmode done ....\n"); + } + } else { + pr_info("[tuner..] atvdemod_state not work ....\n"); + } + } else if (!strncmp(parm[0], "signal_audmode", + strlen("signal_audmode"))) { + int stereo_flag, sap_flag; + + if (get_atvdemod_state() == ATVDEMOD_STATE_WORK) { + if (is_meson_txlx_cpu()) { + update_btsc_mode(1, &stereo_flag, &sap_flag); + pr_info("[tuner..] get signal_audmode done ....\n"); + } + } else { + pr_info("[tuner..] atvdemod_state not work ....\n"); + } + } else if (!strncmp(parm[0], "clk", 3)) { + adc_set_pll_cntl(1, 0x1, NULL); + atvdemod_clk_init(); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + aud_demod_clk_gate(1); + pr_info("atvdemod_clk_init done ....\n"); + } else if (!strcmp(parm[0], "tune")) { + /* val = simple_strtol(parm[1], NULL, 10); */ + } else if (!strcmp(parm[0], "set")) { + if (!strncmp(parm[1], "avout_gain", strlen("avout_gain"))) { + if (kstrtoul(buf + strlen("avout_offset") + 1, + 10, &tmp) == 0) + val = tmp; + atv_dmd_wr_byte(0x0c, 0x01, val & 0xff); + } else if (!strncmp(parm[1], "avout_offset", + strlen("avout_offset"))) { + if (kstrtoul(buf + strlen("avout_offset") + 1, + 10, &tmp) == 0) + val = tmp; + atv_dmd_wr_byte(0x0c, 0x04, val & 0xff); + } else if (!strncmp(parm[1], "atv_gain", + strlen("atv_gain"))) { + if (kstrtoul(buf + strlen("atv_gain") + 1, + 10, &tmp) == 0) + val = tmp; + atv_dmd_wr_byte(0x19, 0x01, val & 0xff); + } else if (!strncmp(parm[1], "atv_offset", + strlen("atv_offset"))) { + if (kstrtoul(buf + strlen("atv_offset") + 1, + 10, &tmp) == 0) + val = tmp; + atv_dmd_wr_byte(0x19, 0x04, val & 0xff); + } + } else if (!strcmp(parm[0], "get")) { + if (!strncmp(parm[1], "avout_gain", strlen("avout_gain"))) { + val = atv_dmd_rd_byte(0x0c, 0x01); + pr_dbg("avout_gain:0x%x\n", val); + } else if (!strncmp(parm[1], "avout_offset", + strlen("avout_offset"))) { + val = atv_dmd_rd_byte(0x0c, 0x04); + pr_dbg("avout_offset:0x%x\n", val); + } else if (!strncmp(parm[1], "atv_gain", + strlen("atv_gain"))) { + val = atv_dmd_rd_byte(0x19, 0x01); + pr_dbg("atv_gain:0x%x\n", val); + } else if (!strncmp(parm[1], "atv_offset", + strlen("atv_offset"))) { + val = atv_dmd_rd_byte(0x19, 0x04); + pr_dbg("atv_offset:0x%x\n", val); + } + } else if (!strncmp(parm[0], "snr_hist", strlen("snr_hist"))) { + data_snr_avg = 0; + for (i = 0; i < 128; i++) { + data_snr[i] = (atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, + 0x50) >> 8); + usleep_range(50 * 1000, 50 * 1000 + 100); + data_snr_avg += data_snr[i]; + } + data_snr_avg = data_snr_avg / 128; + pr_dbg("**********snr_hist_128avg:0x%x(%d)*********\n", + data_snr_avg, + data_snr_avg); + } else if (!strncmp(parm[0], "afc_info", strlen("afc_info"))) { + data_afc = retrieve_vpll_carrier_afc(); + pr_dbg("[amlatvdemod..]afc %d Khz.\n", data_afc); + } else if (!strncmp(parm[0], "ver_info", strlen("ver_info"))) { + pr_dbg("[amlatvdemod..]aml_atvdemod_ver %s.\n", + AMLATVDEMOD_VER); + } else if (!strncmp(parm[0], "audio_autodet", + strlen("audio_autodet"))) { + aml_audiomode_autodet(NULL); + } else if (!strncmp(parm[0], "overmodule_det", + strlen("overmodule_det"))) { + /* unsigned long over_threshold, */ + /* int det_mode = auto_det_mode; */ + aml_atvdemod_overmodule_det(); + } else if (!strncmp(parm[0], "audio_gain_set", + strlen("audio_gain_set"))) { + if (kstrtoul(buf + strlen("audio_gain_set") + 1, 16, &tmp) == 0) + val = tmp; + aml_audio_valume_gain_set(val); + pr_dbg("audio_gain_set : %d\n", val); + } else if (!strncmp(parm[0], "audio_gain_get", + strlen("audio_gain_get"))) { + val = aml_audio_valume_gain_get(); + pr_dbg("audio_gain_get : %d\n", val); + } else if (!strncmp(parm[0], "fix_pwm_adj", + strlen("fix_pwm_adj"))) { + if (kstrtoul(parm[1], 10, &tmp) == 0) { + val = tmp; + aml_fix_PWM_adjust(val); + } + } else if (!strncmp(parm[0], "rs", strlen("rs"))) { + if (kstrtoul(parm[1], 16, &tmp) == 0) + block_addr = tmp; + if (kstrtoul(parm[2], 16, &tmp) == 0) + block_reg = tmp; + if (block_addr < APB_BLOCK_ADDR_TOP) + block_val = atv_dmd_rd_long(block_addr, block_reg); + pr_dbg("rs block_addr:0x%x,block_reg:0x%x,block_val:0x%x\n", + block_addr, + block_reg, block_val); + } else if (!strncmp(parm[0], "ws", strlen("ws"))) { + if (kstrtoul(parm[1], 16, &tmp) == 0) + block_addr = tmp; + if (kstrtoul(parm[2], 16, &tmp) == 0) + block_reg = tmp; + if (kstrtoul(parm[3], 16, &tmp) == 0) + block_val = tmp; + if (block_addr < APB_BLOCK_ADDR_TOP) + atv_dmd_wr_long(block_addr, block_reg, block_val); + pr_dbg("ws block_addr:0x%x,block_reg:0x%x,block_val:0x%x\n", + block_addr, + block_reg, block_val); + block_val = atv_dmd_rd_long(block_addr, block_reg); + pr_dbg("readback_val:0x%x\n", block_val); + } else if (!strncmp(parm[0], "pin_mux", strlen("pin_mux"))) { + aml_atvdemod_dev->pin = devm_pinctrl_get_select( + aml_atvdemod_dev->dev, + aml_atvdemod_dev->pin_name); + pr_dbg("atvdemod agc pinmux name:%s\n", + aml_atvdemod_dev->pin_name); + } else if (!strncmp(parm[0], "snr_cur", strlen("snr_cur"))) { + data_snr_avg = aml_atvdemod_get_snr_ex(); + pr_dbg("**********snr_cur:%d*********\n", data_snr_avg); + } else if (!strncmp(parm[0], "pll_status", strlen("pll_status"))) { + int vpll_lock; + + retrieve_vpll_carrier_lock(&vpll_lock); + if ((vpll_lock & 0x1) == 0) + pr_dbg("visual carrier lock:locked\n"); + else + pr_dbg("visual carrier lock:unlocked\n"); + } else if (!strncmp(parm[0], "line_lock", strlen("line_lock"))) { + int line_lock; + + retrieve_vpll_carrier_line_lock(&line_lock); + if (line_lock == 0) + pr_dbg("line lock:locked\n"); + else + pr_dbg("line lock:unlocked\n"); + } else if (!strncmp(parm[0], "audio_power", strlen("audio_power"))) { + int audio_power = 0; + + retrieve_vpll_carrier_audio_power(&audio_power); + } else if (!strncmp(parm[0], "adc_power", strlen("adc_power"))) { + int adc_power = 0; + + retrieve_adc_power(&adc_power); + pr_dbg("adc_power:%d\n", adc_power); + } else if (!strncmp(parm[0], "search_atv", strlen("search_atv"))) { + unsigned int freq = 0; + struct analog_parameters params; + struct dvb_frontend *fe = NULL; + + fe = &aml_atvdemod_dev->v4l2_fe.v4l2_ad->fe; + + if (kstrtoul(parm[1], 10, &tmp) == 0) + freq = tmp; + + params.frequency = freq; + params.mode = 1; + params.audmode = 0; + params.std = V4L2_STD_PAL_I; + + fe->ops.analog_ops.set_params(fe, ¶ms); + } else if (!strncmp(parm[0], "mode_set", strlen("mode_set"))) { + int priv_cfg = AML_ATVDEMOD_INIT; + struct dvb_frontend *fe = NULL; + + fe = &aml_atvdemod_dev->v4l2_fe.v4l2_ad->fe; + + if (kstrtoul(parm[1], 10, &tmp) == 0) + priv_cfg = tmp; + + fe->ops.analog_ops.set_config(fe, &priv_cfg); + } else + pr_dbg("invalid command\n"); + + kfree(buf_orig); + + return count; +} + +static ssize_t aml_atvdemod_show(struct class *cls, + struct class_attribute *attr, char *buff) +{ + pr_dbg("\n usage:\n"); + pr_dbg("[get soft version] echo ver_info > /sys/class/amlatvdemod/atvdemod_debug\n"); + pr_dbg("[get afc value] echo afc_info > /sys/class/amlatvdemod/atvdemod_debug\n"); + pr_dbg("[reinit atvdemod] echo init > /sys/class/amlatvdemod/atvdemod_debug\n"); + pr_dbg("[get av-out-gain/av-out-offset/atv-gain/atv-offset]:\n" + "echo get av_gain/av_offset/atv_gain/atv_offset > /sys/class/amlatvdemod/atvdemod_debug\n"); + pr_dbg("[set av-out-gain/av-out-offset/atv-gain/atv-offset]:\n" + "echo set av_gain/av_offset/atv_gain/atv_offset val(0~255) > /sys/class/amlatvdemod/atvdemod_debug\n"); + return 0; +} + +static struct class_attribute atvdemod_debug_class_attrs[] = { + __ATTR(atvdemod_debug, 0644, aml_atvdemod_show, aml_atvdemod_store), + __ATTR_NULL +}; + +static void aml_atvdemod_dt_parse(struct aml_atvdemod_device *pdev) +{ + struct device_node *node = NULL; + struct device_node *node_i2c = NULL; + unsigned int val = 0; + const char *str = NULL; + int ret = 0; + + node = pdev->dev->of_node; + if (node) { + ret = of_property_read_u32(node, "reg_23cf", &val); + if (ret) + pr_err("can't find reg_23cf.\n"); + else + pdev->reg_23cf = val; + + ret = of_property_read_u32(node, "audio_gain_val", &val); + if (ret) + pr_err("can't find audio_gain_val.\n"); + else + set_audio_gain_val(val); + + ret = of_property_read_u32(node, "video_gain_val", &val); + if (ret) + pr_err("can't find video_gain_val.\n"); + else + set_video_gain_val(val); + + /* agc pin mux */ + ret = of_property_read_string(node, "pinctrl-names", + &pdev->pin_name); + if (!ret) { +#if 0 + amlatvdemod_devp->pin = devm_pinctrl_get_select( + &pdev->dev, pdev->pin_name); +#endif + pr_err("atvdemod agc pinmux name: %s\n", + pdev->pin_name); + } + + ret = of_property_read_u32(node, "btsc_sap_mode", &val); + if (ret) + pr_err("can't find btsc_sap_mode.\n"); + else + pdev->btsc_sap_mode = val; + + ret = of_property_read_string(node, "tuner", &str); + if (ret) + pr_err("can't find tuner.\n"); + else { + if (!strncmp(str, "mxl661_tuner", + strlen("mxl661_tuner"))) + pdev->tuner_id = AM_TUNER_MXL661; + else if (!strncmp(str, "si2151_tuner", + strlen("si2151_tuner"))) + pdev->tuner_id = AM_TUNER_SI2151; + else if (!strncmp(str, "r840_tuner", + strlen("r840_tuner"))) + pdev->tuner_id = AM_TUNER_R840; + else + pr_err("can't find tuner: %s.\n", str); + } + + node_i2c = of_parse_phandle(node, "tuner_i2c_ada_id", 0); + if (node_i2c) { + pdev->i2c_adp = of_find_i2c_adapter_by_node(node_i2c); + of_node_put(node_i2c); + + if (!pdev->i2c_adp) + pr_err("can't find tuner_i2c_adap.\n"); + } +#if 0 + ret = of_property_read_u32(node, "tuner_i2c_ada_id", &val); + if (ret) + pr_err("can't find tuner_i2c_ada_id.\n"); + else + pdev->i2c_adapter_id = val; +#endif + ret = of_property_read_u32(node, "tuner_i2c_addr", &val); + if (ret) + pr_err("can't find tuner_i2c_addr.\n"); + else + pdev->i2c_addr = val; + } +} + +static int aml_atvdemod_probe(struct platform_device *pdev) +{ + int ret = 0; + struct resource *res = NULL; + int size_io_reg = 0; + struct aml_atvdemod_device *dev = NULL; + + pr_info("%s.\n", __func__); + + dev = kzalloc(sizeof(struct aml_atvdemod_device), GFP_KERNEL); + if (!dev) { + ret = -ENOMEM; + goto fail_alloc_device; + } + + dev->name = ATVDEMOD_DEVICE_NAME; + + dev->cls.name = kzalloc(strlen(ATVDEMOD_DEVICE_NAME), GFP_KERNEL); + if (!dev->cls.name) { + ret = -ENOMEM; + goto fail_alloc_class; + } + + sprintf((char *)dev->cls.name, "%s", ATVDEMOD_DEVICE_NAME); + dev->cls.class_attrs = atvdemod_debug_class_attrs; + ret = class_register(&dev->cls); + if (ret) { + dev_err(&pdev->dev, "class_create fail.\n"); + goto fail_create_class; + } + + dev->dev = &pdev->dev; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "get demod memory resource fail.\n"); + goto fail_get_resource; + } + + size_io_reg = resource_size(res); + dev->demod_reg_base = devm_ioremap_nocache(&pdev->dev, + res->start, size_io_reg); + if (!dev->demod_reg_base) { + dev_err(&pdev->dev, "demod ioremap failed.\n"); + goto fail_get_resource; + } + + pr_info("demod start = 0x%p, size = 0x%x, demod_reg_base = 0x%p.\n", + (void *) res->start, size_io_reg, + dev->demod_reg_base); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "no audio demod memory resource.\n"); + dev->audio_reg_base = NULL; + } else { + size_io_reg = resource_size(res); + dev->audio_reg_base = devm_ioremap_nocache( + &pdev->dev, res->start, size_io_reg); + if (!dev->audio_reg_base) { + dev_err(&pdev->dev, "audio ioremap failed.\n"); + goto fail_get_resource; + } + + pr_info("audio start = 0x%p, size = 0x%x, audio_reg_base = 0x%p.\n", + (void *) res->start, size_io_reg, + dev->audio_reg_base); + } + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + dev->hiu_reg_base = ioremap(0xff63c000, 0x2000); + else + dev->hiu_reg_base = ioremap(0xc883c000, 0x2000); + + pr_info("hiu_reg_base = 0x%p.\n", dev->hiu_reg_base); + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + dev->periphs_reg_base = ioremap(0xff634000, 0x2000); + else + dev->periphs_reg_base = ioremap(0xc8834000, 0x2000); + + pr_info("periphs_reg_base = 0x%p.\n", dev->periphs_reg_base); + + aml_atvdemod_dt_parse(dev); + + dev->v4l2_ad.dev = dev->dev; + dev->v4l2_ad.i2c.addr = dev->i2c_addr; + dev->v4l2_ad.i2c.adapter = dev->i2c_adp; + /* i2c_get_adapter(dev->i2c_adapter_id); */ + dev->v4l2_ad.tuner_id = dev->tuner_id; + ret = v4l2_resister_frontend(&dev->v4l2_ad, &dev->v4l2_fe); + if (ret) { + dev_err(&pdev->dev, "resister v4l2 fail.\n"); + goto fail_register_v4l2; + } + + platform_set_drvdata(pdev, dev); + + amlatvdemod_devp = dev; + + pr_info("probe ok.\n"); + + return 0; + +fail_register_v4l2: +fail_get_resource: + class_unregister(&dev->cls); +fail_create_class: + kfree(dev->cls.name); +fail_alloc_class: + kfree(dev); +fail_alloc_device: + pr_info("[amlatvdemod]: atvdemod_init fail.\n"); + + return ret; +} + +static int aml_atvdemod_remove(struct platform_device *pdev) +{ + struct aml_atvdemod_device *dev = platform_get_drvdata(pdev); + + if (dev == NULL) + return -1; + + class_unregister(&dev->cls); + + v4l2_unresister_frontend(&dev->v4l2_fe); + + amlatvdemod_devp = NULL; + + kfree(dev->cls.name); + kfree(dev); + + pr_dbg("[amlatvdemod] : aml_atvdemod_remove.\n"); + + return 0; +} + +static void aml_atvdemod_shutdown(struct platform_device *pdev) +{ + pr_info("%s done.\n", __func__); +} + +static int aml_atvdemod_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct aml_atvdemod_device *dev = platform_get_drvdata(pdev); + + v4l2_frontend_suspend(&dev->v4l2_fe); + + pr_info("%s: OK\n", __func__); + + return 0; +} + +int aml_atvdemod_resume(struct platform_device *pdev) +{ + struct aml_atvdemod_device *dev = platform_get_drvdata(pdev); + + v4l2_frontend_resume(&dev->v4l2_fe); + + pr_info("%s: OK\n", __func__); + + return 0; +} + +static const struct of_device_id aml_atvdemod_dt_match[] = { + { + .compatible = "amlogic, aml_atvdemod", + }, + { + }, +}; + +static struct platform_driver aml_atvdemod_driver = { + .driver = { + .name = "aml_atvdemod", + .owner = THIS_MODULE, + .of_match_table = aml_atvdemod_dt_match, + }, + .probe = aml_atvdemod_probe, + .remove = aml_atvdemod_remove, + .shutdown = aml_atvdemod_shutdown, + .suspend = aml_atvdemod_suspend, + .resume = aml_atvdemod_resume, +}; + +static int __init aml_atvdemod_init(void) +{ + if (platform_driver_register(&aml_atvdemod_driver)) { + pr_err("failed to register amlatvdemod driver module\n"); + return -ENODEV; + } + + pr_dbg("[amlatvdemod..]%s: driver init ok.\n", __func__); + + return 0; +} + +static void __exit aml_atvdemod_exit(void) +{ + platform_driver_unregister(&aml_atvdemod_driver); + pr_dbg("[amlatvdemod..]%s: driver exit ok.\n", __func__); +} + +MODULE_AUTHOR("nengwen.chen "); +MODULE_DESCRIPTION("aml atv demod device driver"); +MODULE_LICENSE("GPL"); + +module_init(aml_atvdemod_init); +module_exit(aml_atvdemod_exit); diff --git a/drivers/amlogic/atv_demod/atv_demod_driver.h b/drivers/amlogic/atv_demod/atv_demod_driver.h new file mode 100644 index 000000000000..718f91935f8a --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_driver.h @@ -0,0 +1,101 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ATV_DEMOD_DRIVER_H__ +#define __ATV_DEMOD_DRIVER_H__ + +extern int atvdemod_debug_en; + +#include +#include "drivers/media/dvb-core/dvb_frontend.h" +#include "atv_demod_v4l2.h" + +enum aml_tuner_type_t { + AM_TUNER_SI2176 = 1, + AM_TUNER_SI2196 = 2, + AM_TUNER_FQ1216 = 3, + AM_TUNER_HTM = 4, + AM_TUNER_CTC703 = 5, + AM_TUNER_SI2177 = 6, + AM_TUNER_R840 = 7, + AM_TUNER_SI2157 = 8, + AM_TUNER_SI2151 = 9, + AM_TUNER_MXL661 = 10, + AM_TUNER_MXL608 = 11 +}; + +struct aml_atvdemod_parameters { + + struct analog_parameters param; + + unsigned int soundsys;/* A2,BTSC/EIAJ/NICAM */ + unsigned int lock_range; + unsigned int leap_step; + + unsigned int afc_range; + unsigned int tuner_id; + unsigned int if_freq; + unsigned int if_inv; + unsigned int reserved; +}; + +struct aml_atvdemod_device { + char *name; + struct class cls; + struct device *dev; + + unsigned int tuner_id; + unsigned int i2c_addr; + unsigned int i2c_adapter_id; + struct i2c_adapter *i2c_adp; + + unsigned int if_freq; + unsigned int if_inv; + u64 std; + + int fre_offset; + struct pinctrl *pin; + const char *pin_name; + + struct v4l2_adapter v4l2_ad; + struct v4l2_frontend v4l2_fe; + + void __iomem *demod_reg_base; + void __iomem *audio_reg_base; + void __iomem *hiu_reg_base; + void __iomem *periphs_reg_base; + + unsigned int reg_23cf; /* IIR filter */ + int btsc_sap_mode; /*0: off 1:monitor 2:auto */ + +#define ATVDEMOD_STATE_IDEL 0 +#define ATVDEMOD_STATE_WORK 1 +#define ATVDEMOD_STATE_SLEEP 2 + int atvdemod_state; + + int (*demod_reg_write)(unsigned int reg, unsigned int val); + int (*demod_reg_read)(unsigned int reg, unsigned int *val); + + int (*audio_reg_write)(unsigned int reg, unsigned int val); + int (*audio_reg_read)(unsigned int reg, unsigned int *val); + + int (*hiu_reg_write)(unsigned int reg, unsigned int val); + int (*hiu_reg_read)(unsigned int reg, unsigned int *val); + + int (*periphs_reg_write)(unsigned int reg, unsigned int val); + int (*periphs_reg_read)(unsigned int reg, unsigned int *val); +}; + +extern struct aml_atvdemod_device *amlatvdemod_devp; + +#endif /* __ATV_DEMOD_DRIVER_H__ */ diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.c b/drivers/amlogic/atv_demod/atv_demod_ops.c new file mode 100644 index 000000000000..b770520cb3ef --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_ops.c @@ -0,0 +1,460 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +#include + +#include "drivers/media/tuners/tuner-i2c.h" +#include "drivers/media/dvb-core/dvb_frontend.h" +#include "drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h" + +#include "atvdemod_func.h" +#include "atvauddemod_func.h" +#include "atv_demod_debug.h" +#include "atv_demod_driver.h" +#include "atv_demod_ops.h" +#include "atv_demod_v4l2.h" + +#define DEVICE_NAME "aml_atvdemod_fe" + +#define ATVDEMOD_STATE_IDEL 0 +#define ATVDEMOD_STATE_WORK 1 +#define ATVDEMOD_STATE_SLEEP 2 +static int atvdemod_state = ATVDEMOD_STATE_IDEL; + +static DEFINE_MUTEX(atv_demod_list_mutex); +static LIST_HEAD(hybrid_tuner_instance_list); + +unsigned int reg_23cf = 0x88188832; /*IIR filter*/ +module_param(reg_23cf, uint, 0664); +MODULE_PARM_DESC(reg_23cf, "\n reg_23cf\n"); + +static int btsc_sap_mode = 1; /*0: off 1:monitor 2:auto */ +module_param(btsc_sap_mode, int, 0644); +MODULE_DESCRIPTION("btsc sap mode\n"); + +/* + * add interface for audio driver to get atv audio state. + * state: + * 0 - no data. + * 1 - has data. + */ +void aml_fe_get_atvaudio_state(int *state) +{ + int power = 0; + int vpll_lock = 0; + int line_lock = 0; + + if (atvdemod_state == ATVDEMOD_STATE_WORK) { + retrieve_vpll_carrier_lock(&vpll_lock); + retrieve_vpll_carrier_line_lock(&line_lock); + if ((vpll_lock == 0) && (line_lock == 0)) + retrieve_vpll_carrier_audio_power(&power); + } else + pr_err("%s, atv is not work, atvdemod_state: %d.\n", + __func__, atvdemod_state); + + if (power >= 150) + *state = 1; + else + *state = 0; + + pr_info("aml_fe_get_atvaudio_state: %d, power = %d.\n", + *state, power); +} + +int aml_atvdemod_get_btsc_sap_mode(void) +{ + return btsc_sap_mode; +} + +unsigned int atvdemod_scan_mode; /*IIR filter*/ +module_param(atvdemod_scan_mode, uint, 0664); +MODULE_PARM_DESC(atvdemod_scan_mode, "\n atvdemod_scan_mode\n"); + +/* ret:5~100;the val is bigger,the signal is better */ +int aml_atvdemod_get_snr(struct dvb_frontend *fe) +{ +#if 1 + return get_atvdemod_snr_val(); +#else + unsigned int snr_val; + int ret; + + snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; + /* snr_val:900000~0xffffff,ret:5~15 */ + if (snr_val > 900000) + ret = 15 - (snr_val - 900000)*10/(0xffffff - 900000); + /* snr_val:158000~900000,ret:15~30 */ + else if (snr_val > 158000) + ret = 30 - (snr_val - 158000)*15/(900000 - 158000); + /* snr_val:31600~158000,ret:30~50 */ + else if (snr_val > 31600) + ret = 50 - (snr_val - 31600)*20/(158000 - 31600); + /* snr_val:316~31600,ret:50~80 */ + else if (snr_val > 316) + ret = 80 - (snr_val - 316)*30/(31600 - 316); + /* snr_val:0~316,ret:80~100 */ + else + ret = 100 - (316 - snr_val)*20/316; + return ret; +#endif +} + +int aml_atvdemod_get_snr_ex(void) +{ +#if 1 + return get_atvdemod_snr_val(); +#else + unsigned int snr_val; + int ret; + + snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; + /* snr_val:900000~0xffffff,ret:5~15 */ + if (snr_val > 900000) + ret = 15 - (snr_val - 900000)*10/(0xffffff - 900000); + /* snr_val:158000~900000,ret:15~30 */ + else if (snr_val > 158000) + ret = 30 - (snr_val - 158000)*15/(900000 - 158000); + /* snr_val:31600~158000,ret:30~50 */ + else if (snr_val > 31600) + ret = 50 - (snr_val - 31600)*20/(158000 - 31600); + /* snr_val:316~31600,ret:50~80 */ + else if (snr_val > 316) + ret = 80 - (snr_val - 316)*30/(31600 - 316); + /* snr_val:0~316,ret:80~100 */ + else + ret = 100 - (316 - snr_val)*20/316; + return ret; +#endif +} + +int is_atvdemod_work(void) +{ + int ret = 0; + + if (atvdemod_state == ATVDEMOD_STATE_WORK) + ret = 1; + + return ret; +} + +int is_atvdemod_scan_mode(void) +{ + return atvdemod_scan_mode; +} +//EXPORT_SYMBOL(is_atvdemod_scan_mode); + +void set_atvdemod_scan_mode(int val) +{ + atvdemod_scan_mode = val; +} + +int get_atvdemod_state(void) +{ + return atvdemod_state; +} + +void set_atvdemod_state(int state) +{ + atvdemod_state = state; +} + +int atv_demod_enter_mode(void) +{ + int err_code = 0; + +#if 0 + if (atvdemod_state == ATVDEMOD_STATE_WORK) + return 0; +#endif + if (amlatvdemod_devp->pin_name != NULL) + amlatvdemod_devp->pin = + devm_pinctrl_get_select(amlatvdemod_devp->dev, + amlatvdemod_devp->pin_name); + + adc_set_pll_cntl(1, 0x1, NULL); + usleep_range(2000, 2100); + atvdemod_clk_init(); + err_code = atvdemod_init(); + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + aud_demod_clk_gate(1); + atvauddemod_init(); + } + if (err_code) { + pr_dbg("[amlatvdemod..]%s init atvdemod error.\n", __func__); + return err_code; + } + + /* set_aft_thread_enable(1, 0); */ + //memset(&(amlatvdemod_devp->parm), 0, sizeof(amlatvdemod_devp->parm)); + atvdemod_state = ATVDEMOD_STATE_WORK; + + pr_info("%s: OK\n", __func__); + + return 0; +} + +int atv_demod_leave_mode(void) +{ + if (atvdemod_state == ATVDEMOD_STATE_IDEL) + return 0; + + /* set_aft_thread_enable(0, 0); */ + atvdemod_uninit(); + if (amlatvdemod_devp->pin != NULL) { + devm_pinctrl_put(amlatvdemod_devp->pin); + amlatvdemod_devp->pin = NULL; + } + + adc_set_pll_cntl(0, 0x1, NULL); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + aud_demod_clk_gate(0); + //memset(&(amlatvdemod_devp->parm), 0, sizeof(amlatvdemod_devp->parm)); + atvdemod_state = ATVDEMOD_STATE_IDEL; + + pr_info("%s: OK\n", __func__); + + return 0; +} + +static void atv_demod_set_params(struct dvb_frontend *fe, + struct analog_parameters *params) +{ + int ret = -1; + u32 if_info[2] = { 0 }; + struct atv_demod_priv *priv = fe->analog_demod_priv; + struct aml_atvdemod_parameters *atvdemod_param = &priv->atvdemod_param; + + priv->standby = false; + + atvdemod_param->param.frequency = params->frequency; + atvdemod_param->param.mode = params->mode; + atvdemod_param->param.audmode = params->audmode; + atvdemod_param->param.std = params->std; + + /* afc tune disable,must cancel wq before set tuner freq*/ + /* afc_timer_disable(); */ + + if (fe->ops.tuner_ops.set_analog_params) + ret = fe->ops.tuner_ops.set_analog_params(fe, params); + + if (fe->ops.tuner_ops.get_if_frequency) + ret = fe->ops.tuner_ops.get_if_frequency(fe, if_info); + + atvdemod_param->if_inv = if_info[0]; + atvdemod_param->if_freq = if_info[1]; + + if ((atvdemod_param->param.std != amlatvdemod_devp->std) || + (atvdemod_param->tuner_id == AM_TUNER_R840) || + (atvdemod_param->tuner_id == AM_TUNER_SI2151) || + (atvdemod_param->tuner_id == AM_TUNER_MXL661)) { + /* open AGC if needed */ + if (amlatvdemod_devp->pin != NULL) + devm_pinctrl_put(amlatvdemod_devp->pin); + if (amlatvdemod_devp->pin_name) + amlatvdemod_devp->pin = + devm_pinctrl_get_select(amlatvdemod_devp->dev, + amlatvdemod_devp->pin_name); +#if 0 + last_frq = atvdemod_param->param.frequency; + last_std = atvdemod_param->param.std; +#endif + if (atvdemod_param->param.std != amlatvdemod_devp->std) { + amlatvdemod_devp->std = atvdemod_param->param.std; + amlatvdemod_devp->if_freq = atvdemod_param->if_freq; + amlatvdemod_devp->if_inv = atvdemod_param->if_inv; + amlatvdemod_devp->tuner_id = atvdemod_param->tuner_id; + atv_dmd_set_std(); + } else { + atv_dmd_soft_reset(); + return; + } + + if (!is_atvdemod_scan_mode()) + atvauddemod_init(); + + pr_info("[amlatvdemod..]%s set std color %lld, audio type %lld.\n", + __func__, amlatvdemod_devp->std, amlatvdemod_devp->std); + pr_info("[amlatvdemod..]%s set if_freq %d, if_inv %d.\n", + __func__, amlatvdemod_devp->if_freq, + amlatvdemod_devp->if_inv); + } + + pr_err("%s: tuner_id = %d.\n", __func__, atvdemod_param->tuner_id); +} + +static int atv_demod_has_signal(struct dvb_frontend *fe, u16 *signal) +{ + int vpll_lock = 0; + int line_lock = 0; + + retrieve_vpll_carrier_lock(&vpll_lock); + + /* add line lock status for atv scan */ + retrieve_vpll_carrier_line_lock(&line_lock); + + if ((vpll_lock & 0x1) == 0 && line_lock == 0) { + *signal = V4L2_HAS_LOCK; + pr_info("visual carrier lock:locked\n"); + } else { + *signal = V4L2_TIMEDOUT; + pr_info("visual carrier lock:unlocked\n"); + } + + pr_err("%s.\n", __func__); + + return 0; +} + +static void atv_demod_standby(struct dvb_frontend *fe) +{ + if (get_atvdemod_state() != ATVDEMOD_STATE_IDEL) { + atv_demod_leave_mode(); + set_atvdemod_state(ATVDEMOD_STATE_SLEEP); + } + + pr_info("%s: OK\n", __func__); +} + +static void atv_demod_tuner_status(struct dvb_frontend *fe) +{ + pr_err("%s.\n", __func__); +} + +static int atv_demod_get_afc(struct dvb_frontend *fe, s32 *afc) +{ + *afc = retrieve_vpll_carrier_afc(); + + pr_info("%s: afc %d.\n", __func__, *afc); + + return 0; +} + +static void atv_demod_release(struct dvb_frontend *fe) +{ + struct atv_demod_priv *priv = fe->analog_demod_priv; + + atv_demod_leave_mode(); + + mutex_lock(&atv_demod_list_mutex); + + if (priv) + hybrid_tuner_release_state(priv); + + mutex_unlock(&atv_demod_list_mutex); + + fe->analog_demod_priv = NULL; + + pr_err("%s.\n", __func__); +} + +static int atv_demod_set_config(struct dvb_frontend *fe, void *priv_cfg) +{ + int *state = (int *) priv_cfg; + + if (!state) { + pr_err("%s state == NULL.\n", __func__); + return -1; + } + + mutex_lock(&atv_demod_list_mutex); + + if (*state == AML_ATVDEMOD_INIT) { + atv_demod_enter_mode(); + if (fe->ops.tuner_ops.init) + fe->ops.tuner_ops.init(fe); + } else if (*state == AML_ATVDEMOD_UNINIT) { + atv_demod_leave_mode(); + if (fe->ops.tuner_ops.release) + fe->ops.tuner_ops.release(fe); + } else if (*state == AML_ATVDEMOD_RESUME) { + if (get_atvdemod_state() == ATVDEMOD_STATE_SLEEP) + atv_demod_enter_mode(); + if (fe->ops.tuner_ops.resume) + fe->ops.tuner_ops.resume(fe); + } + + mutex_unlock(&atv_demod_list_mutex); + + pr_err("%s done.\n", __func__); + + return 0; +} + +static struct analog_demod_ops atvdemod_ops = { + .info = { + .name = "atv_demod", + }, + .set_params = atv_demod_set_params, + .has_signal = atv_demod_has_signal, + .standby = atv_demod_standby, + .tuner_status = atv_demod_tuner_status, + .get_afc = atv_demod_get_afc, + .release = atv_demod_release, + .set_config = atv_demod_set_config, + .i2c_gate_ctrl = NULL, +}; + +struct dvb_frontend *aml_atvdemod_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, u8 i2c_addr, u32 tuner_id) +{ + int instance = 0; + struct atv_demod_priv *priv = NULL; + + mutex_lock(&atv_demod_list_mutex); + + instance = hybrid_tuner_request_state(struct atv_demod_priv, priv, + hybrid_tuner_instance_list, + i2c_adap, i2c_addr, DEVICE_NAME); + + priv->atvdemod_param.tuner_id = tuner_id; + + switch (instance) { + case 0: + mutex_unlock(&atv_demod_list_mutex); + return NULL; + case 1: + fe->analog_demod_priv = priv; + priv->standby = true; + pr_info("aml_atvdemod found\n"); + break; + default: + fe->analog_demod_priv = priv; + break; + } + + mutex_unlock(&atv_demod_list_mutex); + + fe->ops.info.type = FE_ANALOG; + + memcpy(&fe->ops.analog_ops, &atvdemod_ops, + sizeof(struct analog_demod_ops)); + + switch (tuner_id) { + case AM_TUNER_R840: + break; + case AM_TUNER_SI2151: + v4l2_attach(si2151_attach, fe, i2c_adap, i2c_addr); + break; + case AM_TUNER_MXL661: + v4l2_attach(mxl661_attach, fe, i2c_adap, i2c_addr); + break; + } + + return fe; +} diff --git a/drivers/amlogic/atv_demod/atv_demod_ops.h b/drivers/amlogic/atv_demod/atv_demod_ops.h new file mode 100644 index 000000000000..cb5918432359 --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_ops.h @@ -0,0 +1,45 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ATV_DEMOD_OPS_H__ +#define __ATV_DEMOD_OPS_H__ + +#define AML_ATVDEMOD_RESUME 0x2 +#define AML_ATVDEMOD_INIT 0x1 +#define AML_ATVDEMOD_UNINIT 0x0 + +#include "drivers/media/dvb-core/dvb_frontend.h" +#include "drivers/media/tuners/tuner-i2c.h" + +#include "atv_demod_driver.h" + +struct atv_demod_priv { + struct tuner_i2c_props i2c_props; + struct list_head hybrid_tuner_instance_list; + + bool standby; + + struct aml_atvdemod_parameters atvdemod_param; +}; + +extern int atv_demod_enter_mode(void); + +struct dvb_frontend *aml_atvdemod_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, u8 i2c_addr, u32 tuner_id); + +extern struct dvb_frontend *mxl661_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, u8 i2c_addr); +extern struct dvb_frontend *si2151_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c_adap, u8 i2c_addr); + +#endif /* __ATV_DEMOD_OPS_H__ */ diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.c b/drivers/amlogic/atv_demod/atv_demod_v4l2.c new file mode 100644 index 000000000000..071f25846e0c --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.c @@ -0,0 +1,1383 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "atvdemod_func.h" + +#include "atv_demod_debug.h" +#include "atv_demod_v4l2.h" +#include "atv_demod_driver.h" +#include "atv_demod_ops.h" + + +#define DEVICE_NAME "v4l2_frontend" + +static DEFINE_MUTEX(v4l2_fe_mutex); +/* static int v4l2_shutdown_timeout;*/ + + +#define AFC_BEST_LOCK 50 +#define ATV_AFC_500KHZ 500000 +#define ATV_AFC_1_0MHZ 1000000 +#define ATV_AFC_2_0MHZ 2000000 + +static int tuner_status_cnt = 8; /* 4-->16 test on sky mxl661 */ +module_param(tuner_status_cnt, int, 0644); +MODULE_DESCRIPTION("after write a freq, max cnt value of read tuner status\n"); + +static int slow_mode; +module_param(slow_mode, int, 0644); +MODULE_DESCRIPTION("search the channel by slow_mode,by add +1MHz\n"); + +typedef int (*hook_func_t) (void); +hook_func_t aml_fe_hook_atv_status; +hook_func_t aml_fe_hook_hv_lock; +hook_func_t aml_fe_hook_get_fmt; + +void aml_fe_hook_cvd(hook_func_t atv_mode, hook_func_t cvd_hv_lock, + hook_func_t get_fmt) +{ + aml_fe_hook_atv_status = atv_mode; + aml_fe_hook_hv_lock = cvd_hv_lock; + aml_fe_hook_get_fmt = get_fmt; + pr_dbg("[aml_fe]%s\n", __func__); +} +EXPORT_SYMBOL(aml_fe_hook_cvd); + +static v4l2_std_id demod_fmt_2_v4l2_std(int fmt) +{ + v4l2_std_id std = 0; + + switch (fmt) { + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + std = V4L2_STD_PAL_DK; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + std = V4L2_STD_PAL_I; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + std = V4L2_STD_PAL_BG; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: + std = V4L2_STD_PAL_M; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M: + std = V4L2_STD_NTSC_M; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: + std = V4L2_STD_SECAM_L; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3: + std = V4L2_STD_SECAM_DK; + break; + default: + pr_err("%s: unsupport fmt: 0x%0x.\n", __func__, fmt); + } + + return std; +} + +static v4l2_std_id trans_tvin_fmt_to_v4l2_std(int fmt) +{ + v4l2_std_id std = 0; + + switch (fmt) { + case TVIN_SIG_FMT_CVBS_NTSC_M: + std = V4L2_STD_NTSC; + break; + case TVIN_SIG_FMT_CVBS_NTSC_443: + std = V4L2_STD_NTSC_443; + break; + case TVIN_SIG_FMT_CVBS_PAL_I: + std = V4L2_STD_PAL_I; + break; + case TVIN_SIG_FMT_CVBS_PAL_M: + std = V4L2_STD_PAL_M; + break; + case TVIN_SIG_FMT_CVBS_PAL_60: + std = V4L2_STD_PAL_60; + break; + case TVIN_SIG_FMT_CVBS_PAL_CN: + std = V4L2_STD_PAL_Nc; + break; + case TVIN_SIG_FMT_CVBS_SECAM: + std = V4L2_STD_SECAM; + break; + default: + pr_err("%s err fmt: 0x%x\n", __func__, fmt); + break; + } + return std; +} + +static void v4l2_fe_try_analog_format(struct v4l2_frontend *v4l2_fe, + bool auto_search_std, v4l2_std_id *video_fmt, int *audio_fmt) +{ + struct dvb_frontend *fe = &v4l2_fe->v4l2_ad->fe; + struct v4l2_analog_parameters *p = &v4l2_fe->params; + struct analog_parameters params; + int i = 0; + int try_vfmt_cnt = 300; + int varify_cnt = 0; + v4l2_std_id std_bk = 0; + int audio = 0; + + if (auto_search_std == true) { + for (i = 0; i < try_vfmt_cnt; i++) { + if (aml_fe_hook_get_fmt == NULL) { + pr_err("%s: aml_fe_hook_get_fmt == NULL.\n", + __func__); + break; + } + std_bk = aml_fe_hook_get_fmt(); + if (std_bk) { + varify_cnt++; + pr_dbg("get varify_cnt:%d, cnt:%d, std_bk:0x%x\n", + varify_cnt, i, + (unsigned int) std_bk); + if ((v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_R840 + && varify_cnt > 0) + || varify_cnt > 3) + break; + } + + if (i == (try_vfmt_cnt / 3) || + (i == (try_vfmt_cnt / 3) * 2)) { + /* Before enter search, + * need set the std, + * then, try others std. + */ + if (p->std & V4L2_STD_PAL) + p->std = V4L2_STD_NTSC_M; + else if (p->std & V4L2_STD_NTSC) + p->std = V4L2_STD_SECAM_L; + else if (p->std & V4L2_STD_SECAM) + p->std = V4L2_STD_PAL_DK; + + p->frequency += 1; + params.frequency = p->frequency; + params.mode = p->flag; + params.audmode = p->audmode; + params.std = p->std; + + fe->ops.analog_ops.set_params(fe, ¶ms); + } + usleep_range(30 * 1000, 30 * 1000 + 100); + } + + pr_dbg("get std_bk cnt:%d, std_bk: 0x%x\n", + i, (unsigned int) std_bk); + + if (std_bk == 0) { + pr_err("[%s] failed to get v fmt !!\n", __func__); + pr_err("[%s] vfmt assume PAL !!\n", __func__); + std_bk = TVIN_SIG_FMT_CVBS_PAL_I; + p->std = V4L2_STD_PAL_I; + p->frequency += 1; + params.frequency = p->frequency; + params.mode = p->flag; + params.audmode = p->audmode; + params.std = p->std; + + fe->ops.analog_ops.set_params(fe, ¶ms); + + usleep_range(20 * 1000, 20 * 1000 + 100); + } + + std_bk = trans_tvin_fmt_to_v4l2_std(std_bk); + } else { + /* Only search std by user setting, + * so no need tvafe identify signal. + */ + std_bk = p->std; + } + + *video_fmt = std_bk; + + if (std_bk == V4L2_STD_NTSC) { +#if 0 /* For TV Signal Generator(TG39) test, NTSC need support other audio.*/ + amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK); + audio = aml_audiomode_autodet(fe); + audio = demod_fmt_2_v4l2_std(audio); +#if 0 + if (audio == V4L2_STD_PAL_M) + audio = V4L2_STD_NTSC_M; + else + std_bk = V4L2_COLOR_STD_PAL; +#endif +#else /* Now, force to NTSC_M, Ours demod only support M for NTSC.*/ + audio = V4L2_STD_NTSC_M; +#endif + } else if (std_bk == V4L2_STD_SECAM) { + audio = V4L2_STD_SECAM_L; + } else { + /*V4L2_COLOR_STD_PAL*/ + amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK); + audio = aml_audiomode_autodet(fe); + audio = demod_fmt_2_v4l2_std(audio); +#if 0 /* Why do this to me? We need support PAL_M.*/ + if (audio == V4L2_STD_PAL_M) { + audio = demod_fmt_2_v4l2_std(broad_std_except_pal_m); + pr_err("select audmode 0x%x\n", audio); + } +#endif + } + + *audio_fmt = audio; +} + +static int v4l2_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq, + int maxafcfreq, int isAutoSearch) +{ + struct dvb_frontend *fe = &v4l2_fe->v4l2_ad->fe; + struct v4l2_analog_parameters *p = &v4l2_fe->params; + struct analog_parameters params; + int afc = 100; + __u32 set_freq; + int count = 25; + int lock_cnt = 0; + static int freq_success; + static int temp_freq, temp_afc; + struct timespec time_now; + static struct timespec success_time; + + pr_dbg("[%s] freq_success: %d, freq: %d, minfreq: %d, maxfreq: %d\n", + __func__, freq_success, p->frequency, minafcfreq, maxafcfreq); + + /* avoid more search the same program, except < 45.00Mhz */ + if (abs(p->frequency - freq_success) < 3000000 + && p->frequency > 45000000) { + ktime_get_ts(&time_now); + //if (debug_fe & 0x2) + pr_err("%s: tv_sec now:%ld,tv_sec success:%ld\n", + __func__, time_now.tv_sec, success_time.tv_sec); + /* beyond 10s search same frequency is ok */ + if ((time_now.tv_sec - success_time.tv_sec) < 10) + return -1; + } + + /*do the auto afc make sure the afc<50k or the range from api */ + if ((fe->ops.analog_ops.get_afc || fe->ops.tuner_ops.get_afc) && + fe->ops.tuner_ops.set_analog_params) { + + set_freq = p->frequency; + while (abs(afc) > AFC_BEST_LOCK) { + if (v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_SI2151 || + v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_R840) + usleep_range(20 * 1000, 20 * 1000 + 100); + else if (v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_MXL661) + usleep_range(30 * 1000, 30 * 1000 + 100); + + if (fe->ops.analog_ops.get_afc && + ((v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_R840) || + (v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_SI2151) || + (v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_MXL661))) + fe->ops.analog_ops.get_afc(fe, &afc); + else if (fe->ops.tuner_ops.get_afc) + fe->ops.tuner_ops.get_afc(fe, &afc); + + //if (debug_fe & 0x2) + pr_err("[%s] get afc %d khz, freq %u.\n", + __func__, afc, p->frequency); + + if (afc == 0xffff) { + /*last lock, but this unlock,so try get afc*/ + if (lock_cnt > 0) { + p->frequency = temp_freq + + temp_afc * 1000; + pr_err("%s, force lock, f:%d\n", + __func__, p->frequency); + break; + } + + afc = 500; + } else { + lock_cnt++; + temp_freq = p->frequency; + if (afc > 50) + temp_afc = 500; + else if (afc < -50) + temp_afc = -500; + else + temp_afc = afc; + } + + if (((abs(afc) > (500 - AFC_BEST_LOCK)) + && (abs(afc) < (500 + AFC_BEST_LOCK)) + && (abs(afc) != 500)) + || ((abs(afc) == 500) && (lock_cnt > 0))) { + p->frequency += afc * 1000; + break; + } + + if (afc >= (500 + AFC_BEST_LOCK)) + afc = 500; + + p->frequency += afc * 1000; + + if (unlikely(p->frequency > maxafcfreq)) { + pr_err("[%s]:[%d] is exceed maxafcfreq[%d]\n", + __func__, p->frequency, maxafcfreq); + p->frequency = set_freq; + return -1; + } +#if 0 /*if enable ,it would miss program*/ + if (unlikely(c->frequency < minafcfreq)) { + pr_dbg("[%s]:[%d] is exceed minafcfreq[%d]\n", + __func__, c->frequency, minafcfreq); + c->frequency = set_freq; + return -1; + } +#endif + if (likely(!(count--))) { + pr_err("[%s]:exceed the afc count\n", __func__); + p->frequency = set_freq; + return -1; + } + + /* delete it will miss program + * when c->frequency equal program frequency + */ + p->frequency++; + if (fe->ops.tuner_ops.set_analog_params) { + params.frequency = p->frequency; + params.mode = p->flag; + params.audmode = p->audmode; + params.std = p->std; + fe->ops.tuner_ops.set_analog_params(fe, + ¶ms); + } + } + + freq_success = p->frequency; + ktime_get_ts(&success_time); + //if (debug_fe & 0x2) + pr_err("[%s] get afc %d khz done, freq %u.\n", + __func__, afc, p->frequency); + } + + return 0; +} + +static enum v4l2_search v4l2_frontend_search(struct v4l2_frontend *v4l2_fe) +{ + struct analog_parameters params; + struct dvb_frontend *fe = &v4l2_fe->v4l2_ad->fe; + struct v4l2_analog_parameters *p = &v4l2_fe->params; + enum v4l2_status tuner_state = V4L2_TIMEDOUT; + enum v4l2_status ade_state = V4L2_TIMEDOUT; + bool pll_lock = false; + /*struct atv_status_s atv_status;*/ + __u32 set_freq = 0; + __u32 minafcfreq = 0, maxafcfreq = 0; + __u32 afc_step = 0; + int tuner_status_cnt_local = tuner_status_cnt; + v4l2_std_id std_bk = 0; + int audio = 0; + int double_check_cnt = 1; + bool auto_search_std = false; + int search_count = 0; + int ret = -1; + +#ifdef DEBUG_TIME_CUS + unsigned int time_start, time_end, time_delta; + + time_start = jiffies_to_msecs(jiffies); +#endif + + if (unlikely(!fe || !p || + !fe->ops.tuner_ops.get_status || + !fe->ops.analog_ops.has_signal)) { + pr_err("[%s] error: NULL function or pointer.\n", __func__); + return V4L2_SEARCH_INVALID; + } + + if (p->afc_range == 0) { + pr_err("[%s]:afc_range == 0, skip the search\n", __func__); + return V4L2_SEARCH_INVALID; + } + + pr_err("[%s] afc_range: [%d], tuner type: [%d], freq: [%d].\n", + __func__, p->afc_range, + v4l2_fe->v4l2_ad->tuner_id, p->frequency); + + /* backup the freq by api */ + set_freq = p->frequency; + + /* Before enter search, need set the std first. + * If set p->analog.std == 0, will search all std (PAL/NTSC/SECAM), + * and need tvafe identify signal type. + */ + if (p->std == 0) { + p->std = V4L2_STD_PAL_I; + auto_search_std = true; + pr_dbg("%s, user analog.std is 0, so set it to PAL | I.\n", + __func__); + } + + /*afc tune disable*/ + //TODO: afc_timer_disable(); + //analog_search_flag = 1; + + /*set the afc_range and start freq*/ + minafcfreq = p->frequency - p->afc_range; + maxafcfreq = p->frequency + p->afc_range; + + /*from the current freq start, and set the afc_step*/ + /*if step is 2Mhz,r840 will miss program*/ + if (slow_mode || (v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_R840) + || (p->afc_range == ATV_AFC_1_0MHZ)) { + pr_dbg("[%s] slow mode to search the channel\n", __func__); + afc_step = ATV_AFC_1_0MHZ; + } else if (!slow_mode) { + afc_step = ATV_AFC_2_0MHZ; + } else { + pr_dbg("[%s] slow mode to search the channel\n", __func__); + afc_step = ATV_AFC_1_0MHZ; + } + + /**enter auto search mode**/ + pr_dbg("%s Auto search user std: 0x%08x\n", + __func__, (unsigned int) p->std); + +#ifdef DEBUG_TIME_CUS + time_end = jiffies_to_msecs(jiffies); + time_delta = time_end - time_start; + pr_dbg("[%s]: time_delta_001:%d ms,afc_step:%d\n", + __func__, time_delta, afc_step); +#endif + + while (minafcfreq <= p->frequency && + p->frequency <= maxafcfreq) { + + if (fe->ops.analog_ops.set_params) { + params.frequency = p->frequency; + params.mode = p->flag; + params.audmode = p->audmode; + params.std = p->std; + fe->ops.analog_ops.set_params(fe, ¶ms); + } + + pr_dbg("[%s] [%d] is processing, [min=%d, max=%d].\n", + __func__, p->frequency, minafcfreq, maxafcfreq); + + pll_lock = false; + tuner_status_cnt_local = tuner_status_cnt; + do { + if (v4l2_fe->v4l2_ad->tuner_id == AM_TUNER_MXL661) { + usleep_range(30 * 1000, 30 * 1000 + 100); + } else if (v4l2_fe->v4l2_ad->tuner_id + == AM_TUNER_R840) { + usleep_range(20 * 1000, 20 * 1000 + 100); + fe->ops.tuner_ops.get_status(fe, + &tuner_state); + } else { + /*fee->tuner->drv->id == AM_TUNER_SI2151)*/ + usleep_range(10 * 1000, 10 * 1000 + 100); + } + + fe->ops.analog_ops.has_signal(fe, (u16 *)&ade_state); + tuner_status_cnt_local--; + if (((ade_state == V4L2_HAS_LOCK || + tuner_state == V4L2_HAS_LOCK) && + (v4l2_fe->v4l2_ad->tuner_id + != AM_TUNER_R840)) || + ((ade_state == V4L2_HAS_LOCK && + tuner_state == V4L2_HAS_LOCK) && + (v4l2_fe->v4l2_ad->tuner_id + == AM_TUNER_R840))) { + pll_lock = true; + break; + } + + if (tuner_status_cnt_local == 0) + break; + } while (1); + + if (pll_lock) { + + pr_dbg("[%s] freq: [%d] pll lock success\n", + __func__, p->frequency); +#if 0 /* In get_pll_status has line_lock check.*/ + if (fee->tuner->drv->id == AM_TUNER_MXL661) { + fe->ops.analog_ops.get_atv_status(fe, + &atv_status); + if (atv_status.atv_lock) + usleep_range(30 * 1000, + 30 * 1000 + 100); + } +#endif + ret = v4l2_fe_afc_closer(v4l2_fe, minafcfreq, + maxafcfreq + ATV_AFC_500KHZ, 1); + if (ret == 0) { + v4l2_fe_try_analog_format(v4l2_fe, + auto_search_std, + &std_bk, &audio); + + pr_dbg("[%s] freq:%d, std_bk:0x%x, audmode:0x%x, search OK.\n", + __func__, p->frequency, + (unsigned int) std_bk, audio); + + if (std_bk != 0) { + p->audmode = audio; + p->std = std_bk; + /*avoid std unenable */ + p->frequency -= 1; + std_bk = 0; + } +#ifdef DEBUG_TIME_CUS + time_end = jiffies_to_msecs(jiffies); + time_delta = time_end - time_start; + pr_dbg("[ATV_SEARCH_SUCCESS]%s: time_delta:%d ms\n", + __func__, time_delta); +#endif + /*sync param */ + //aml_fe_analog_sync_frontend(fe); + /*afc tune enable*/ + //analog_search_flag = 0; + //afc_timer_enable(fe); + return V4L2_SEARCH_SUCCESS; + } + } + + /*avoid sound format is not match after search over */ + if (std_bk != 0) { + p->std = std_bk; + + params.frequency = p->frequency; + params.mode = p->flag; + params.audmode = p->audmode; + params.std = p->std; + + fe->ops.analog_ops.set_params(fe, ¶ms); + std_bk = 0; + } + + pr_dbg("[%s] freq[analog.std:0x%08x] is[%d] unlock\n", + __func__, + (uint32_t) p->std, p->frequency); + + ++search_count; + if (p->frequency >= 44200000 && + p->frequency <= 44300000 && + double_check_cnt) { + double_check_cnt--; + p->frequency -= afc_step; + pr_err("%s 44.25Mhz double check\n", __func__); + } else + p->frequency += afc_step * ((search_count % 2) ? + -search_count : search_count); + +#ifdef DEBUG_TIME_CUS + time_end = jiffies_to_msecs(jiffies); + time_delta = time_end - time_start; + pr_dbg("[ATV_SEARCH_FAILED]%s: time_delta:%d ms\n", + __func__, time_delta); +#endif + } + +#ifdef DEBUG_TIME_CUS + time_end = jiffies_to_msecs(jiffies); + time_delta = time_end - time_start; + pr_dbg("[ATV_SEARCH_FAILED]%s: time_delta:%d ms\n", + __func__, time_delta); +#endif + + pr_dbg("[%s] [%d] over of range [min=%d, max=%d], search failed.\n", + __func__, p->frequency, minafcfreq, maxafcfreq); + p->frequency = set_freq; + /*afc tune enable*/ + //analog_search_flag = 0; + //afc_timer_enable(fe); + return DVBFE_ALGO_SEARCH_FAILED; +} + + +static int v4l2_frontend_get_event(struct v4l2_frontend *v4l2_fe, + struct v4l2_frontend_event *event, int flags) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct v4l2_fe_events *events = &fepriv->events; + + pr_err("%s.\n", __func__); + + if (events->overflow) { + events->overflow = 0; + return -EOVERFLOW; + } + + if (events->eventw == events->eventr) { + int ret; + + if (flags & O_NONBLOCK) + return -EWOULDBLOCK; + + up(&fepriv->sem); + + ret = wait_event_interruptible(events->wait_queue, + events->eventw != events->eventr); + + if (down_interruptible(&fepriv->sem)) + return -ERESTARTSYS; + + if (ret < 0) { + pr_err("ret = %d.\n", ret); + return ret; + } + } + + mutex_lock(&events->mtx); + *event = events->events[events->eventr]; + events->eventr = (events->eventr + 1) % MAX_EVENT; + mutex_unlock(&events->mtx); + + return 0; +} + +static void v4l2_frontend_add_event(struct v4l2_frontend *v4l2_fe, + enum v4l2_status status) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct v4l2_fe_events *events = &fepriv->events; + struct v4l2_frontend_event *e = NULL; + int wp; + + pr_err("%s.\n", __func__); + + mutex_lock(&events->mtx); + + wp = (events->eventw + 1) % MAX_EVENT; + if (wp == events->eventr) { + events->overflow = 1; + events->eventr = (events->eventr + 1) % MAX_EVENT; + } + + e = &events->events[events->eventw]; + e->status = status; + + memcpy(&e->parameters, &v4l2_fe->params, + sizeof(struct v4l2_analog_parameters)); + + events->eventw = wp; + + mutex_unlock(&events->mtx); + + wake_up_interruptible(&events->wait_queue); +} + +static void v4l2_frontend_wakeup(struct v4l2_frontend *v4l2_fe) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + fepriv->wakeup = 1; + wake_up_interruptible(&fepriv->wait_queue); +} + +static void v4l2_frontend_clear_events(struct v4l2_frontend *v4l2_fe) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct v4l2_fe_events *events = &fepriv->events; + + mutex_lock(&events->mtx); + events->eventr = events->eventw; + mutex_unlock(&events->mtx); +} + +static int v4l2_frontend_is_exiting(struct v4l2_frontend *v4l2_fe) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + if (fepriv->exit != V4L2_FE_NO_EXIT) + return 1; +#if 0 + if (time_after_eq(jiffies, fepriv->release_jiffies + + v4l2_shutdown_timeout * HZ)) + return 1; +#endif + return 0; +} + +static int v4l2_frontend_should_wakeup(struct v4l2_frontend *v4l2_fe) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + if (fepriv->wakeup) { + fepriv->wakeup = 0; + return 1; + } + + return v4l2_frontend_is_exiting(v4l2_fe); +} + +static int v4l2_frontend_thread(void *data) +{ + struct v4l2_frontend *v4l2_fe = (struct v4l2_frontend *) data; + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + enum v4l2_status s = V4L2_TIMEDOUT; + unsigned long timeout = 0; + + pr_err("%s: thread start.\n", __func__); + + fepriv->delay = 3 * HZ; + fepriv->status = 0; + fepriv->wakeup = 0; + + set_freezable(); + while (1) { + up(&fepriv->sem); /* is locked when we enter the thread... */ +restart: + timeout = wait_event_interruptible_timeout(fepriv->wait_queue, + v4l2_frontend_should_wakeup(v4l2_fe) + || kthread_should_stop() + || freezing(current), fepriv->delay); + + if (kthread_should_stop() || + v4l2_frontend_is_exiting(v4l2_fe)) { + /* got signal or quitting */ + fepriv->exit = V4L2_FE_NORMAL_EXIT; + break; + } + + if (try_to_freeze()) + goto restart; + + if (down_interruptible(&fepriv->sem)) + break; + + /* pr_dbg("%s: state = %d.\n", __func__, fepriv->state); */ + if (fepriv->state & V4L2FE_STATE_RETUNE) { + pr_err("%s: Retune requested, V4L2FE_STATE_RETUNE.\n", + __func__); + fepriv->state = V4L2FE_STATE_TUNED; + } + /* Case where we are going to search for a carrier + * User asked us to retune again + * for some reason, possibly + * requesting a search with a new set of parameters + */ + if ((fepriv->algo_status & V4L2_SEARCH_AGAIN) + && !(fepriv->state & V4L2FE_STATE_IDLE)) { + if (v4l2_fe->search) { + fepriv->algo_status = v4l2_fe->search(v4l2_fe); + /* We did do a search as was requested, + * the flags are now unset as well and has + * the flags wrt to search. + */ + } else { + fepriv->algo_status &= ~V4L2_SEARCH_AGAIN; + } + } + /* Track the carrier if the search was successful */ + if (fepriv->algo_status == V4L2_SEARCH_SUCCESS) { + s = FE_HAS_LOCK; + } else { + /*dev->algo_status |= AML_ATVDEMOD_ALGO_SEARCH_AGAIN;*/ + if (fepriv->algo_status != V4L2_SEARCH_INVALID) { + fepriv->delay = HZ / 2; + s = V4L2_TIMEDOUT; + } + } + + if (s != fepriv->status) { + /* update event list */ + v4l2_frontend_add_event(v4l2_fe, s); + fepriv->status = s; + if (!(s & FE_HAS_LOCK)) { + fepriv->delay = HZ / 10; + fepriv->algo_status |= V4L2_SEARCH_AGAIN; + } else { + fepriv->delay = 60 * HZ; + } + } + } + + fepriv->thread = NULL; + if (kthread_should_stop()) + fepriv->exit = V4L2_FE_DEVICE_REMOVED; + else + fepriv->exit = V4L2_FE_NO_EXIT; + + /* memory barrier */ + mb(); + + v4l2_frontend_wakeup(v4l2_fe); + + pr_err("%s: thread exit state = %d.\n", __func__, fepriv->state); + + return 0; +} + +static void v4l2_frontend_stop(struct v4l2_frontend *v4l2_fe) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + pr_err("%s.\n", __func__); + + fepriv->exit = V4L2_FE_NORMAL_EXIT; + + /* memory barrier */ + mb(); + + if (!fepriv->thread) + return; + + kthread_stop(fepriv->thread); + + sema_init(&fepriv->sem, 1); + fepriv->state = V4L2FE_STATE_IDLE; + + /* paranoia check in case a signal arrived */ + if (fepriv->thread) + pr_err("%s: warning: thread %p won't exit\n", + __func__, fepriv->thread); +} + +static int v4l2_frontend_start(struct v4l2_frontend *v4l2_fe) +{ + int ret = 0; + struct task_struct *thread = NULL; + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + pr_err("%s.\n", __func__); + + if (fepriv->thread) { + if (fepriv->exit == V4L2_FE_NO_EXIT) + return 0; + + v4l2_frontend_stop(v4l2_fe); + } + + if (signal_pending(current)) + return -EINTR; + + if (down_interruptible(&fepriv->sem)) + return -EINTR; + + fepriv->state = V4L2FE_STATE_IDLE; + fepriv->exit = V4L2_FE_NO_EXIT; + fepriv->thread = NULL; + + /* memory barrier */ + mb(); + + thread = kthread_run(v4l2_frontend_thread, v4l2_fe, + "v4l2_frontend_thread"); + if (IS_ERR(thread)) { + ret = PTR_ERR(thread); + pr_err("%s: failed to start kthread (%d)\n", __func__, ret); + up(&fepriv->sem); + return ret; + } + + fepriv->thread = thread; + + return 0; +} + + +static int v4l2_set_frontend(struct v4l2_frontend *v4l2_fe, + struct v4l2_analog_parameters *params) +{ + u32 freq_min = 0; + u32 freq_max = 0; + struct analog_parameters p; + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct dvb_frontend *fe = &v4l2_fe->v4l2_ad->fe; + + pr_err("%s.\n", __func__); + + freq_min = fe->ops.tuner_ops.info.frequency_min; + freq_max = fe->ops.tuner_ops.info.frequency_max; + + if (freq_min == 0 || freq_max == 0) + pr_err("%s: demod or tuner frequency limits undefined.\n", + __func__); + + /* range check: frequency */ + if ((freq_min && params->frequency < freq_min) || + (freq_max && params->frequency > freq_max)) { + pr_err("%s: frequency %u out of range (%u..%u).\n", + __func__, params->frequency, + freq_min, freq_max); + return -EINVAL; + } + + /* + * Initialize output parameters to match the values given by + * the user. FE_SET_FRONTEND triggers an initial frontend event + * with status = 0, which copies output parameters to userspace. + */ + //dtv_property_legacy_params_sync_ex(fe, &fepriv->parameters_out); + memcpy(&v4l2_fe->params, params, sizeof(struct v4l2_analog_parameters)); + + fepriv->state = V4L2FE_STATE_RETUNE; + + /* Request the search algorithm to search */ + fepriv->algo_status |= V4L2_SEARCH_AGAIN; + if (params->flag) { + /*dvb_frontend_add_event(fe, 0); */ + v4l2_frontend_clear_events(v4l2_fe); + v4l2_frontend_wakeup(v4l2_fe); + } else if (fe->ops.analog_ops.set_params) { + /* TODO:*/ + p.frequency = params->frequency; + p.std = params->std; + p.audmode = params->audmode; + fe->ops.analog_ops.set_params(fe, &p); + } + + fepriv->status = 0; + + return 0; +} + +static int v4l2_get_frontend(struct v4l2_frontend *v4l2_fe, + struct v4l2_analog_parameters *p) +{ + + return 0; +} + +static int v4l2_frontend_set_mode(struct v4l2_frontend *v4l2_fe, + unsigned long params) +{ + int ret = 0; + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct analog_demod_ops *analog_ops = NULL; + int priv_cfg = 0; + + pr_err("%s: params = %ld.\n", __func__, params); + + fepriv->state = V4L2FE_STATE_IDLE; + + analog_ops = &v4l2_fe->v4l2_ad->fe.ops.analog_ops; + + if (params) + priv_cfg = AML_ATVDEMOD_INIT; + else + priv_cfg = AML_ATVDEMOD_UNINIT; + + if (analog_ops && analog_ops->set_config) + ret = analog_ops->set_config(&v4l2_fe->v4l2_ad->fe, &priv_cfg); + + return ret; +} + +static void v4l2_frontend_vdev_release(struct video_device *dev) +{ + pr_err("%s.\n", __func__); +} + +static ssize_t v4l2_frontend_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static ssize_t v4l2_frontend_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static unsigned int v4l2_frontend_poll(struct file *filp, + struct poll_table_struct *pts) +{ + struct v4l2_frontend *v4l2_fe = video_get_drvdata(video_devdata(filp)); + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + poll_wait(filp, &fepriv->events.wait_queue, pts); + + if (fepriv->events.eventw != fepriv->events.eventr) + return (POLLIN | POLLRDNORM | POLLPRI); + + pr_err("%s.\n", __func__); + return 0; +} + +static long v4l2_frontend_ioctl(struct file *filp, void *fh, bool valid_prio, + unsigned int cmd, void *arg) +{ + int ret = 0; + struct v4l2_frontend *v4l2_fe = video_get_drvdata(video_devdata(filp)); + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + pr_err("%s: cmd = 0x%x.\n", __func__, cmd); + if (fepriv->exit != V4L2_FE_NO_EXIT) + return -ENODEV; + + if (down_interruptible(&fepriv->sem)) + return -ERESTARTSYS; + + switch (cmd) { + case V4L2_SET_FRONTEND: + ret = v4l2_set_frontend(v4l2_fe, + (struct v4l2_analog_parameters *) arg); + break; + + case V4L2_GET_FRONTEND: + ret = v4l2_get_frontend(v4l2_fe, + (struct v4l2_analog_parameters *) arg); + break; + + case V4L2_GET_EVENT: + ret = v4l2_frontend_get_event(v4l2_fe, + (struct v4l2_frontend_event *) arg, + filp->f_flags); + break; + + case V4L2_SET_MODE: + ret = v4l2_frontend_set_mode(v4l2_fe, (unsigned long) arg); + break; + + default: + break; + } + + up(&fepriv->sem); + + return ret; +} + +static int v4l2_frontend_open(struct file *filp) +{ + int ret = 0; + void *p = NULL; + struct v4l2_frontend *v4l2_fe = video_get_drvdata(video_devdata(filp)); + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct dvb_tuner_ops *tuner_ops = &v4l2_fe->v4l2_ad->fe.ops.tuner_ops; + + if (tuner_ops->init == NULL) { + switch (v4l2_fe->v4l2_ad->tuner_id) { + case AM_TUNER_R840: + break; + case AM_TUNER_SI2151: + p = v4l2_attach(si2151_attach, &v4l2_fe->v4l2_ad->fe, + v4l2_fe->v4l2_ad->i2c.adapter, + v4l2_fe->v4l2_ad->i2c.addr); + break; + case AM_TUNER_MXL661: + p = v4l2_attach(mxl661_attach, &v4l2_fe->v4l2_ad->fe, + v4l2_fe->v4l2_ad->i2c.adapter, + v4l2_fe->v4l2_ad->i2c.addr); + break; + } + + if (p == NULL) + pr_err("%s: v4l2_attach error.\n", __func__); + } + + ret = v4l2_frontend_start(v4l2_fe); + + fepriv->events.eventr = fepriv->events.eventw = 0; + + pr_err("%s.\n", fepriv->v4l2dev->name); + pr_err("%s.\n", __func__); + + return ret; +} + +static int v4l2_frontend_release(struct file *filp) +{ + struct v4l2_frontend *v4l2_fe = video_get_drvdata(video_devdata(filp)); + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + pr_err("%s.\n", fepriv->v4l2dev->name); + pr_err("%s.\n", __func__); + + return 0; +} + +static const struct v4l2_file_operations v4l2_fe_fops = { + .owner = THIS_MODULE, + .read = v4l2_frontend_read, + .write = v4l2_frontend_write, + .poll = v4l2_frontend_poll, + .unlocked_ioctl = video_ioctl2, + .open = v4l2_frontend_open, + .release = v4l2_frontend_release, +}; + +static int v4l2_frontend_vidioc_g_audio(struct file *file, void *fh, + struct v4l2_audio *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_s_audio(struct file *filp, void *fh, + const struct v4l2_audio *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_g_tuner(struct file *filp, void *fh, + struct v4l2_tuner *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_s_tuner(struct file *filp, void *fh, + const struct v4l2_tuner *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_g_frequency(struct file *filp, void *fh, + struct v4l2_frequency *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_s_frequency(struct file *filp, void *fh, + const struct v4l2_frequency *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_enum_freq_bands(struct file *filp, void *fh, + struct v4l2_frequency_band *band) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_g_modulator(struct file *filp, void *fh, + struct v4l2_modulator *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static int v4l2_frontend_vidioc_s_modulator(struct file *filp, void *fh, + const struct v4l2_modulator *a) +{ + pr_err("%s.\n", __func__); + return 0; +} + +int v4l2_frontend_vidioc_streamon(struct file *filp, void *fh, + enum v4l2_buf_type i) +{ + pr_err("%s.\n", __func__); + return 0; +} + +int v4l2_frontend_vidioc_streamoff(struct file *filp, void *fh, + enum v4l2_buf_type i) +{ + pr_err("%s.\n", __func__); + return 0; +} + +static const struct v4l2_ioctl_ops v4l2_fe_ioctl_ops = { + .vidioc_g_audio = v4l2_frontend_vidioc_g_audio, + .vidioc_s_audio = v4l2_frontend_vidioc_s_audio, + .vidioc_g_tuner = v4l2_frontend_vidioc_g_tuner, + .vidioc_s_tuner = v4l2_frontend_vidioc_s_tuner, + .vidioc_g_frequency = v4l2_frontend_vidioc_g_frequency, + .vidioc_s_frequency = v4l2_frontend_vidioc_s_frequency, + .vidioc_enum_freq_bands = v4l2_frontend_vidioc_enum_freq_bands, + .vidioc_g_modulator = v4l2_frontend_vidioc_g_modulator, + .vidioc_s_modulator = v4l2_frontend_vidioc_s_modulator, + .vidioc_streamon = v4l2_frontend_vidioc_streamon, + .vidioc_streamoff = v4l2_frontend_vidioc_streamoff, + .vidioc_default = v4l2_frontend_ioctl, +}; + +static struct video_device aml_atvdemod_vdev = { + .fops = &v4l2_fe_fops, + .ioctl_ops = &v4l2_fe_ioctl_ops, + .name = DEVICE_NAME, + .release = v4l2_frontend_vdev_release, + .vfl_dir = VFL_DIR_TX, +}; + +int v4l2_resister_frontend(struct v4l2_adapter *v4l2_ad, + struct v4l2_frontend *v4l2_fe) +{ + int ret = 0; + struct v4l2_frontend_private *fepriv = NULL; + struct v4l2_atvdemod_device *v4l2dev = NULL; + + if (v4l2_ad == NULL || v4l2_fe == NULL) { + pr_err("NULL pointer.\n"); + return -1; + } + + if (mutex_lock_interruptible(&v4l2_fe_mutex)) + return -ERESTARTSYS; + + v4l2_fe->frontend_priv = kzalloc(sizeof(struct v4l2_frontend_private), + GFP_KERNEL); + if (v4l2_fe->frontend_priv == NULL) { + mutex_unlock(&v4l2_fe_mutex); + pr_err("kzalloc fail.\n"); + return -ENOMEM; + } + + v4l2_fe->search = v4l2_frontend_search; + v4l2_fe->v4l2_ad = v4l2_ad; + fepriv = v4l2_fe->frontend_priv; + + fepriv->v4l2dev = kzalloc(sizeof(struct v4l2_atvdemod_device), + GFP_KERNEL); + if (fepriv->v4l2dev == NULL) { + ret = -ENOMEM; + goto malloc_fail; + } + + v4l2dev = fepriv->v4l2dev; + v4l2dev->name = DEVICE_NAME; + v4l2dev->dev = v4l2_fe->v4l2_ad->dev; + + snprintf(v4l2dev->v4l2_dev.name, sizeof(v4l2dev->v4l2_dev.name), + "%s", DEVICE_NAME); + + ret = v4l2_device_register(v4l2dev->dev, &v4l2dev->v4l2_dev); + if (ret) { + pr_err("register v4l2_device fail.\n"); + goto v4l2_fail; + } + + v4l2dev->video_dev = &aml_atvdemod_vdev; + v4l2dev->video_dev->v4l2_dev = &v4l2dev->v4l2_dev; + + video_set_drvdata(v4l2dev->video_dev, v4l2_fe); + + v4l2dev->video_dev->dev.init_name = DEVICE_NAME; + ret = video_register_device(v4l2dev->video_dev, + VFL_TYPE_GRABBER, -1); + if (ret) { + pr_err("register video device fail.\n"); + goto vdev_fail; + } + + if (!aml_atvdemod_attach(&v4l2_ad->fe, v4l2_ad->i2c.adapter, + v4l2_ad->i2c.addr, v4l2_ad->tuner_id)) { + pr_err("atvdemod attach fail.\n"); + goto attach_fail; + } + + sema_init(&fepriv->sem, 1); + init_waitqueue_head(&fepriv->wait_queue); + init_waitqueue_head(&fepriv->events.wait_queue); + mutex_init(&fepriv->events.mtx); + + mutex_unlock(&v4l2_fe_mutex); + + pr_err("resister aml atv demod device.\n"); + + return 0; + +attach_fail: + +vdev_fail: + v4l2_device_unregister(&v4l2dev->v4l2_dev); + +malloc_fail: + kfree(v4l2_fe->frontend_priv); +v4l2_fail: + mutex_unlock(&v4l2_fe_mutex); + + return ret; +} + +int v4l2_unresister_frontend(struct v4l2_frontend *v4l2_fe) +{ + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + + mutex_lock(&v4l2_fe_mutex); + + video_unregister_device(fepriv->v4l2dev->video_dev); + v4l2_device_unregister(&fepriv->v4l2dev->v4l2_dev); + + v4l2_frontend_stop(v4l2_fe); + + mutex_unlock(&v4l2_fe_mutex); + + pr_err("unregister aml atv demod device.\n"); + + return 0; +} + +int v4l2_frontend_suspend(struct v4l2_frontend *v4l2_fe) +{ + int ret = 0; + struct dvb_frontend *fe = &v4l2_fe->v4l2_ad->fe; + struct dvb_tuner_ops tuner_ops = fe->ops.tuner_ops; + struct analog_demod_ops analog_ops = fe->ops.analog_ops; + + pr_info("%s.\n", __func__); + + if (analog_ops.standby) + analog_ops.standby(fe); + + if (tuner_ops.suspend) + tuner_ops.suspend(fe); + + return ret; +} + +int v4l2_frontend_resume(struct v4l2_frontend *v4l2_fe) +{ + int ret = 0; + struct v4l2_frontend_private *fepriv = v4l2_fe->frontend_priv; + struct dvb_frontend *fe = &v4l2_fe->v4l2_ad->fe; + struct dvb_tuner_ops tuner_ops = fe->ops.tuner_ops; + struct analog_demod_ops analog_ops = fe->ops.analog_ops; + int priv_cfg = AML_ATVDEMOD_RESUME; + + pr_info("%s.\n", __func__); + + if (analog_ops.set_config) + analog_ops.set_config(fe, &priv_cfg); + + if (tuner_ops.resume) + tuner_ops.resume(fe); + + fepriv->state = V4L2FE_STATE_RETUNE; + v4l2_frontend_wakeup(v4l2_fe); + + return ret; +} diff --git a/drivers/amlogic/atv_demod/atv_demod_v4l2.h b/drivers/amlogic/atv_demod/atv_demod_v4l2.h new file mode 100644 index 000000000000..bf79df8dbd11 --- /dev/null +++ b/drivers/amlogic/atv_demod/atv_demod_v4l2.h @@ -0,0 +1,179 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ATV_DEMOD_V4L2_H__ +#define __ATV_DEMOD_V4L2_H__ + +#include +#include "drivers/media/dvb-core/dvb_frontend.h" + +/** generic attach function. */ +#ifdef CONFIG_AMLOGIC_ATV_DEMOD +#define v4l2_attach(FUNCTION, ARGS...) ({ \ + void *__r = NULL; \ + typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ + if (__a) { \ + __r = (void *) __a(ARGS); \ + if (__r == NULL) \ + symbol_put(FUNCTION); \ + } else { \ + pr_err("V4L2_FE: Unable to find " \ + "symbol "#FUNCTION"()\n"); \ + } \ + __r; \ +}) + +#else + +#define v4l2_attach(FUNCTION, ARGS...) ({ \ + FUNCTION(ARGS); \ +}) +#endif /* CONFIG_MEDIA_ATTACH */ + +#define V4L2_FE_NO_EXIT 0 +#define V4L2_FE_NORMAL_EXIT 1 +#define V4L2_FE_DEVICE_REMOVED 2 + +#define V4L2FE_STATE_IDLE 1 +#define V4L2FE_STATE_RETUNE 2 +#define V4L2FE_STATE_TUNING_FAST 4 +#define V4L2FE_STATE_TUNING_SLOW 8 +#define V4L2FE_STATE_TUNED 16 +#define V4L2FE_STATE_ZIGZAG_FAST 32 +#define V4L2FE_STATE_ZIGZAG_SLOW 64 +#define V4L2FE_STATE_DISEQC 128 +#define V4L2FE_STATE_ERROR 256 +#define V4L2FE_STATE_WAITFORLOCK (V4L2FE_STATE_TUNING_FAST |\ + V4L2FE_STATE_TUNING_SLOW | V4L2FE_STATE_ZIGZAG_FAST |\ + V4L2FE_STATE_ZIGZAG_SLOW | V4L2FE_STATE_DISEQC) +#define V4L2FE_STATE_SEARCHING_FAST (V4L2FE_STATE_TUNING_FAST |\ + V4L2FE_STATE_ZIGZAG_FAST) +#define V4L2FE_STATE_SEARCHING_SLOW (V4L2FE_STATE_TUNING_SLOW |\ + V4L2FE_STATE_ZIGZAG_SLOW) +#define V4L2FE_STATE_LOSTLOCK (V4L2FE_STATE_ZIGZAG_FAST |\ + V4L2FE_STATE_ZIGZAG_SLOW) + +#define V4L2_SET_FRONTEND _IOW('V', 105, struct v4l2_analog_parameters) +#define V4L2_GET_FRONTEND _IOR('V', 106, struct v4l2_analog_parameters) +#define V4L2_GET_EVENT _IOR('V', 107, struct v4l2_frontend_event) +#define V4L2_SET_MODE _IO('V', 108) + +struct v4l2_analog_parameters { + unsigned int frequency; + unsigned int audmode; + unsigned int soundsys; /*A2,BTSC,EIAJ,NICAM */ + v4l2_std_id std; + unsigned int flag; + unsigned int afc_range; + unsigned int reserved; +}; + +enum v4l2_status { + V4L2_HAS_SIGNAL = 0x01, /* found something above the noise level */ + V4L2_HAS_CARRIER = 0x02, /* found a DVB signal */ + V4L2_HAS_VITERBI = 0x04, /* FEC is stable */ + V4L2_HAS_SYNC = 0x08, /* found sync bytes */ + V4L2_HAS_LOCK = 0x10, /* everything's working... */ + V4L2_TIMEDOUT = 0x20, /* no lock within the last ~2 seconds */ + V4L2_REINIT = 0x40, /* frontend was reinitialized, */ +}; /* application is recommended to reset */ + /* DiSEqC, tone and parameters */ + +enum v4l2_search { + V4L2_SEARCH_SUCCESS = (1 << 0), + V4L2_SEARCH_ASLEEP = (1 << 1), + V4L2_SEARCH_FAILED = (1 << 2), + V4L2_SEARCH_INVALID = (1 << 3), + V4L2_SEARCH_AGAIN = (1 << 4), + V4L2_SEARCH_ERROR = (1 << 31), +}; + +struct v4l2_frontend_event { + enum v4l2_status status; + struct v4l2_analog_parameters parameters; +}; + +#define MAX_EVENT 8 + +struct v4l2_fe_events { + struct v4l2_frontend_event events[MAX_EVENT]; + int eventw; + int eventr; + int overflow; + wait_queue_head_t wait_queue; + struct mutex mtx; +}; + +struct v4l2_frontend_private { + struct v4l2_atvdemod_device *v4l2dev; + + struct v4l2_fe_events events; + struct semaphore sem; + struct list_head list_head; + wait_queue_head_t wait_queue; + struct task_struct *thread; + unsigned long release_jiffies; + unsigned int exit; + unsigned int wakeup; + enum v4l2_status status; + unsigned int delay; + + unsigned int state; + enum v4l2_search algo_status; +}; + +struct v4l2_adapter { + struct device *dev; + + struct dvb_frontend fe; + + struct i2c_client i2c; + unsigned int tuner_id; +}; + +struct v4l2_frontend { + struct v4l2_adapter *v4l2_ad; + + void *frontend_priv; + void *tuner_priv; + void *analog_priv; + + struct v4l2_analog_parameters params; + + enum v4l2_search (*search)(struct v4l2_frontend *v4l2_fe); +}; + +struct v4l2_atvdemod_device { + char *name; + struct class *clsp; + struct device *dev; + + struct v4l2_device v4l2_dev; + struct video_device *video_dev; + + struct mutex lock; + + struct i2c_client i2c; + unsigned int tuner_id; + + enum v4l2_search (*search)(struct v4l2_atvdemod_device *dev); +}; + +int v4l2_resister_frontend(struct v4l2_adapter *v4l2_ad, + struct v4l2_frontend *v4l2_fe); +int v4l2_unresister_frontend(struct v4l2_frontend *v4l2_fe); + +int v4l2_frontend_suspend(struct v4l2_frontend *v4l2_fe); +int v4l2_frontend_resume(struct v4l2_frontend *v4l2_fe); + +#endif // __ATV_DEMOD_V4L2_H__ diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.c b/drivers/amlogic/atv_demod/atvauddemod_func.c new file mode 100644 index 000000000000..97b62fcece49 --- /dev/null +++ b/drivers/amlogic/atv_demod/atvauddemod_func.c @@ -0,0 +1,1260 @@ +#ifndef __ATVAUDDEMOD_FUN_H +#define __ATVAUDDEMOD_FUN_H + +#include +#include +#include + +#include +#include + +#include "atv_demod_debug.h" +#include "atvauddemod_func.h" +#include "aud_demod_settings.c" + +/* #define AUDIO_MOD_DET_INTERNAL */ + +int ademod_debug_en; +module_param(ademod_debug_en, int, 0644); +MODULE_PARM_DESC(ademod_debug_en, "\n ademod_debug_en for audio demod debug\n"); + +static int btsc_detect_delay = 10; +module_param(btsc_detect_delay, int, 0644); +MODULE_PARM_DESC(btsc_detect_delay, "\n btsc_detect_delay for btsc detect delay\n"); + +int signal_audmode; +module_param(signal_audmode, int, 0644); +MODULE_PARM_DESC(signal_audmode, "\n signal_audmode for btsc signal audio mode\n"); + +static unsigned int audio_thd_threshold1 = 0x1000; +module_param(audio_thd_threshold1, uint, 0644); +MODULE_PARM_DESC(audio_thd_threshold1, "\n audio_thd_threshold1\n"); + +static unsigned int audio_thd_threshold2 = 0xf00; +module_param(audio_thd_threshold2, uint, 0644); +MODULE_PARM_DESC(audio_thd_threshold2, "\n audio_thd_threshold2\n"); + +int deem_75u_30[7] = {10, 6, 0, -971, 0, -44, 97}; +int deem_75u_40[7] = {10, 6, 0, -971, 0, -26, 80}; +int deem_75u_50[7] = {10, 6, 0, -971, 0, -16, 69}; +int deem_75u[7] = {10, 6, 0, -971, 0, 12, 41}; +int deem_50u[7] = {10, 6, 0, -945, 0, 18, 60}; + +int deem_j17[7] = {10, 6, 0, -1012, 0, 124, -112}; + +int lmr15k_0[7] = {10, 6, 778, -1739, 310, -557, 310}; +int lmr15k_3[7] = {10, 6, 864, -1783, 430, -756, 430}; +int lmr15k_1[7] = {10, 6, 721, -1712, 57, -95, 71}; +int lmr15k_2[7] = {10, 6, 942, -1830, 7, 17, 112}; +int lmr15k_4[7] = {10, 6, 1000, -1872, 19, 48, 85}; +int lpr15k_0[7] = {10, 6, 778, -1739, 310, -557, 310}; +int lpr15k_3[7] = {10, 6, 864, -1783, 430, -756, 430}; +int lpr15k_1[7] = {10, 6, 721, -1712, 57, -95, 71}; +int lpr15k_2[7] = {10, 6, 942, -1830, 7, 17, 112}; +int lpr15k_4[7] = {10, 6, 1000, -1872, 19, 48, 85}; + +int lmr15k_4_4[7] = {10, 6, 885, -1325, 617, -651, 617}; +int lmr15k_1_4[7] = {10, 6, 638, -1102, 508, -455, 508}; +int lmr15k_0_4[7] = {10, 6, 405, -853, 382, -188, 382}; +int lmr15k_2_4[7] = {10, 6, 196, -609, 257, 97, 257}; +int lmr15k_3_4[7] = {10, 6, 62, -445, 173, 294, 173}; +int lpr15k_4_4[7] = {10, 6, 885, -1325, 617, -651, 617}; +int lpr15k_1_4[7] = {10, 6, 638, -1102, 508, -455, 508}; +int lpr15k_0_4[7] = {10, 6, 405, -853, 382, -188, 382}; +int lpr15k_2_4[7] = {10, 6, 196, -609, 257, 97, 257}; +int lpr15k_3_4[7] = {10, 6, 62, -445, 173, 294, 173}; + +int lmr15k_btsc_0[7] = {10, 6, 997, -1865, 1011, -1865, 1011}; +int lmr15k_btsc_1[7] = {10, 6, 794, -1673, 698, -1673, 1121}; +int lmr15k_btsc_2[7] = {10, 6, 836, -1773, 137, -188, 137}; +int lmr15k_btsc_3[7] = {10, 6, 736, -1724, 16, 4, 16}; +int lmr15k_btsc_4[7] = {10, 6, 961, -1851, 342, -550, 342}; +int lpr15k_btsc_0[7] = {10, 6, 997, -1865, 1011, -1865, 1011}; +int lpr15k_btsc_1[7] = {10, 6, 794, -1673, 698, -1673, 1121}; +int lpr15k_btsc_2[7] = {10, 6, 836, -1773, 137, -188, 137}; +int lpr15k_btsc_3[7] = {10, 6, 736, -1724, 16, 4, 16}; +int lpr15k_btsc_4[7] = {10, 6, 961, -1851, 342, -550, 342}; + +int btsc_pilot[7] = {10, 6, 1014, -1881, -5, 0, 5}; + +int fix_deem0[7] = {10, 6, 0, -1014, 0, -74, 85}; +int fix_deem1[7] = {10, 6, 0, -969, 0, -7, 62}; +int fix_deem2[7] = {9, 5, 0, 0, 0, 0, 512}; + +int qfilter0[7] = {10, 6, 838, -1828, 788, -1576, 788}; +int qfilter1[7] = {10, 6, 459, -1434, -330, 0, 330}; +int qfilter2[7] = {9, 5, 0, 0, 0, 0, 512}; +int pfilter0[7] = {10, 6, 0, -972, 0, -920, 920}; +int pfilter1[7] = {10, 6, 0, -1023, 0, 29, 29}; + +static int thd_flag; +static uint32_t thd_tmp_v; +static uint8_t thd_cnt; + +static inline uint32_t R_AUDDEMOD_REG(uint32_t reg) +{ + unsigned int val; + + atvaudiodem_reg_read(reg<<2, &val); + return val; +} + +static inline void W_AUDDEMOD_REG(uint32_t reg, + const uint32_t val) +{ + atvaudiodem_reg_write(reg<<2, val); +} + +static inline void W_AUDDEMOD_BIT(uint32_t reg, + const uint32_t value, + const uint32_t start, + const uint32_t len) +{ + W_AUDDEMOD_REG(reg, ((R_AUDDEMOD_REG(reg) & + ~(((1L << (len)) - 1) << (start))) | + (((value) & ((1L << (len)) - 1)) << (start)))); +} + +static inline uint32_t R_AUDDEMOD_BIT(uint32_t reg, + const uint32_t start, + const uint32_t len) +{ + uint32_t val; + + val = ((R_AUDDEMOD_REG(reg) >> (start)) & ((1L << (len)) - 1)); + + return val; +} + +void adec_wr_reg(uint32_t reg, uint32_t val) +{ + atvaudiodem_reg_write(reg<<2, val); +} + +uint32_t adec_rd_reg(uint32_t addr) +{ + return R_AUDDEMOD_REG(addr); +} + + +void set_filter(int *filter, int start_addr, int taps) +{ + int i = 0; + int filter_len = (taps+1)>>1; + int tmp = 0; + int tmp_addr = 0; + + tmp_addr = start_addr; + for (i = 0; i < filter_len; i++) { + if ((i&1) == 1) { + tmp = ((tmp&0xffff))|((filter[i]&0xffff)<<16); + adec_wr_reg(tmp_addr, tmp); + /* pr_info("[reg0x%x] = 0x%x\n",tmp_addr,tmp); */ + tmp_addr += 1; + } else { + tmp = filter[i]; + if (i == filter_len-1) { + adec_wr_reg(tmp_addr, tmp); + /*pr_info("[reg0x%x] = 0x%x\n",tmp_addr,tmp);*/ + } + } + } +} + +void set_iir(int *filter, int start_addr) +{ + unsigned int reg32; + + reg32 = (filter[6]&0xffff) | ((filter[5]&0xffff)<<16); + adec_wr_reg(start_addr, reg32); + + reg32 = (filter[4]&0xffff) | ((filter[3]&0xffff)<<16); + adec_wr_reg(start_addr+1, reg32); + + reg32 = (filter[2]&0xffff) | ((filter[1]&0xff)<<16) + |((filter[0]&0xff)<<24); + adec_wr_reg(start_addr+2, reg32); +} + +void bypass_iir(int start_addr) +{ + adec_wr_reg(start_addr, 512); + adec_wr_reg(start_addr+1, 0); + adec_wr_reg(start_addr+2, 0x09050000); +} + +void bypass_15k_iir(void) +{ + pr_info("Bypass 15k LPF\n"); + bypass_iir(ADDR_IIR_LPR_15K_0); + bypass_iir(ADDR_IIR_LPR_15K_1); + bypass_iir(ADDR_IIR_LPR_15K_2); + bypass_iir(ADDR_IIR_LPR_15K_3); + bypass_iir(ADDR_IIR_LPR_15K_4); + bypass_iir(ADDR_IIR_LMR_15K_0); + bypass_iir(ADDR_IIR_LMR_15K_1); + bypass_iir(ADDR_IIR_LMR_15K_2); + bypass_iir(ADDR_IIR_LMR_15K_3); + bypass_iir(ADDR_IIR_LMR_15K_4); +} + +void set_lpf15k(void) +{ + set_iir(lpr15k_0, ADDR_IIR_LPR_15K_0); + set_iir(lpr15k_1, ADDR_IIR_LPR_15K_1); + set_iir(lpr15k_2, ADDR_IIR_LPR_15K_2); + set_iir(lpr15k_3, ADDR_IIR_LPR_15K_3); + set_iir(lpr15k_4, ADDR_IIR_LPR_15K_4); + + set_iir(lpr15k_0, ADDR_IIR_LMR_15K_0); + set_iir(lpr15k_1, ADDR_IIR_LMR_15K_1); + set_iir(lpr15k_2, ADDR_IIR_LMR_15K_2); + set_iir(lpr15k_3, ADDR_IIR_LMR_15K_3); + set_iir(lpr15k_4, ADDR_IIR_LMR_15K_4); +} + +void set_deem(int deem_mode) +{ + if (deem_mode == AUDIO_DEEM_75US) { + set_iir(deem_75u_40, ADDR_IIR_LPR_DEEMPHASIS); + set_iir(deem_75u_40, ADDR_IIR_LMR_DEEMPHASIS); + } else if (deem_mode == AUDIO_DEEM_50US) { + set_iir(deem_50u, ADDR_IIR_LPR_DEEMPHASIS); + set_iir(deem_50u, ADDR_IIR_LMR_DEEMPHASIS); + } else if (deem_mode == AUDIO_DEEM_J17) { + set_iir(deem_j17, ADDR_IIR_LPR_DEEMPHASIS); + set_iir(deem_j17, ADDR_IIR_LMR_DEEMPHASIS); + } else { + bypass_iir(ADDR_IIR_LPR_DEEMPHASIS); + bypass_iir(ADDR_IIR_LMR_DEEMPHASIS); + } +} + +void set_i2s_intrp(int freq) +{ + double fs; /* system clock */ + double fout = 48e3; /* I2S output frequency */ + double rate = 16*8; /* system clock/data sample frequency*/ + int inc = 150; + double m1, m2, m3; + int M1, M2, M3; + double s1; + int S1; + int count; + + int tmp; + + fs = FCLK; + m1 = fs/fout/32*inc; + m2 = fs/fout*inc; + m3 = rate*inc; + M1 = (int) (m1); + M2 = (int) (m2); + M3 = (int) (m3); + + s1 = 1/(rate*inc)*4096*4096; + S1 = (int) (s1); + + count = (int)(fs/fout/32/2); + + tmp = (count<<16)|S1; + + adec_wr_reg((SRC_CTRL0), M1); + adec_wr_reg((SRC_CTRL1), M2); + adec_wr_reg((SRC_CTRL2), M3); + adec_wr_reg((SRC_CTRL3), inc); + adec_wr_reg((SRC_CTRL4), inc); + adec_wr_reg((SRC_CTRL5), inc); + adec_wr_reg((SRC_CTRL9), tmp); +} + +void set_general(void) +{ + /* Initial the bb filter */ + + set_filter(filter_bb_10k, ADDR_BB_FIR0_A_COEF, 16); + set_filter(filter_bb_20k, ADDR_BB_FIR0_B_COEF, 16); + + set_filter(filter_bb_10k, ADDR_BB_FIR1_A_COEF, 16); + set_filter(filter_bb_20k, ADDR_BB_FIR1_B_COEF, 16); + + set_filter(filter_bb_10k, ADDR_BB_FIR2_A_COEF, 16); + set_filter(filter_bb_20k, ADDR_BB_FIR2_B_COEF, 16); + + + adec_wr_reg(ADDR_BB_MUTE_THRESHOLD0, 0x0000000f); + adec_wr_reg(ADDR_BB_MUTE_THRESHOLD1, 0x0000000f); + adec_wr_reg(ADDR_BB_MUTE_THRESHOLD2, 0x0000000f); + +#if 0 + write_reg32(ADDR_BB_NOISE_THRESHOLD1, 0x00000a3d); + write_reg32(ADDR_BB_NOISE_THRESHOLD2, 0x00000a3d); +#else + adec_wr_reg(ADDR_BB_NOISE_THRESHOLD0, 0x000013dc); + adec_wr_reg(ADDR_BB_NOISE_THRESHOLD1, 0x000013dc); + adec_wr_reg(ADDR_BB_NOISE_THRESHOLD2, 0x000013dc); +#endif + + adec_wr_reg(SAP_DET_THD, 0x200); +} + +void set_btsc(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_BTSC); + + aa = (int)(4.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((15.734e3*5)/(FCLK/4/16)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + set_filter(filter_150k, ADDR_DDC_FIR0_COEF, 65); + + set_filter(filter_sap_15k_2, ADDR_DDC_FIR1_COEF, 65); + + set_iir(fix_deem0, ADDR_IIR_FIXED_DEEM_0); + set_iir(fix_deem1, ADDR_IIR_FIXED_DEEM_1); + set_iir(fix_deem2, ADDR_IIR_FIXED_DEEM_2); + + set_iir(qfilter0, ADDR_IIR_Q_FILTER_0); + set_iir(qfilter1, ADDR_IIR_Q_FILTER_1); + set_iir(qfilter2, ADDR_IIR_Q_FILTER_2); + + set_iir(pfilter0, ADDR_IIR_P_FILTER_0); + set_iir(pfilter1, ADDR_IIR_P_FILTER_1); + + set_iir(lpr15k_btsc_0, ADDR_IIR_LPR_15K_0); + set_iir(lpr15k_btsc_1, ADDR_IIR_LPR_15K_1); + set_iir(lpr15k_btsc_2, ADDR_IIR_LPR_15K_2); + set_iir(lpr15k_btsc_3, ADDR_IIR_LPR_15K_3); + set_iir(lpr15k_btsc_4, ADDR_IIR_LPR_15K_4); + + set_iir(lpr15k_btsc_0, ADDR_IIR_LMR_15K_0); + set_iir(lpr15k_btsc_1, ADDR_IIR_LMR_15K_1); + set_iir(lpr15k_btsc_2, ADDR_IIR_LMR_15K_2); + set_iir(lpr15k_btsc_3, ADDR_IIR_LMR_15K_3); + set_iir(lpr15k_btsc_4, ADDR_IIR_LMR_15K_4); + + + set_iir(btsc_pilot, ADDR_IIR_PILOT_0); + set_iir(btsc_pilot, ADDR_IIR_PILOT_1); + set_iir(btsc_pilot, ADDR_IIR_PILOT_2); + + set_deem(0); + + adec_wr_reg(ADDR_EXPANDER_SPECTRAL_ADJ, 0x198); + + adec_wr_reg(ADDR_EXPANDER_GAIN_ADJ, 0x02e0); + adec_wr_reg(ADDR_EXPANDER_B2C_ADJ, 0x3e7d); + + adec_wr_reg(ADDR_LMR_ADJ, 0x1e8); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x3015); + adec_wr_reg(ADDR_SAP_ADJ, 0x2ef); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + pr_info("Set Btsc relative setting done\n"); +} + +void set_a2k(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_A2_K); + + set_filter(filter_50k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_50k, ADDR_DDC_FIR1_COEF, 65); + + + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, A2K_STEREO_DTO); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, A2K_DUAL_DTO); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, A2K_INDICATOR_DTO); + + + aa = (int)(4.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((4.724212e6-4.5e6)/(FCLK/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + aa = (int)((55.0699e3+149.9)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((55.0699e3+276.0)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((55.0699e3)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + + set_lpf15k(); + set_deem(0); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); + + adec_wr_reg((ADDR_SEL_CTRL), 0x1000); +} + +void set_a2g(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_A2_BG); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(5.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((5.7421875e6-5.5e6)/(FCLK/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + aa = (int)((54.6875e3+117.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((54.6875e3+27)/(FCLK/16/44.1)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((54.6875e3)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + + set_lpf15k(); + set_deem(1); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); +} + +void set_a2bg(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_A2_BG); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(5.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((5.7421875e6-5.5e6)/(FCLK/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + aa = (int)((54.6875e3+117.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((54.6875e3+27)/(FCLK/16/44.1)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((54.6875e3)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + + set_lpf15k(); + set_deem(1); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); +} + +void set_a2dk1(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_A2_DK1); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((6.2578125e6-6.5e6)/(FCLK/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + aa = (int)((54.6875e3+117.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((54.6875e3+27)/(FCLK/16/44.1)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((54.6875e3)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + + set_lpf15k(); + set_deem(1); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); +} + +void set_a2dk2(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_A2_DK2); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((6.7421875e6-6.5e6)/(FCLK/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + aa = (int)((54.6875e3+117.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((54.6875e3+27)/(FCLK/16/44.1)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((54.6875e3)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + + set_lpf15k(); + set_deem(1); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); +} + +void set_a2dk3(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_A2_DK3); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((5.7421875e6-6.5e6)/(FCLK/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + aa = (int)((54.6875e3+117.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((54.6875e3+27)/(FCLK/16/44.1)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((54.6875e3)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + + set_lpf15k(); + set_deem(1); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x3e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x010); + adec_wr_reg(ADDR_IIR_SPEED_CTRL, 0xd65d7f7f); +} + +void set_eiaj(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_EIAJ); + + /* DDC FILTER */ + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + + aa = (int)(4.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + aa = (int)((15.734e3*2)/(FCLK/4/16)*1024.0*1024.0*8.0); + aa = (0x80e40); + adec_wr_reg(ADDR_DDC_FREQ1, aa); + + + aa = (int)((15.734e3*3.5+982.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_STEREO_DTO, aa); + aa = (int)((15.734e3*3.5+922.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_DUAL_DTO, aa); + aa = (int)((15.734e3*3.5)/(FCLK/16/4)*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_INDICATOR_CENTER_DTO, aa); + +#if 1 + set_filter(filter_sap_15k_2, ADDR_DDC_FIR1_COEF, 65); + + set_lpf15k(); + + set_deem(0); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x1); + adec_wr_reg(ADDR_LMR_ADJ, 0x3c0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x2e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x410); +#else + set_filter(filter_sap_15k_4, ADDR_DDC_FIR1_COEF, 65); + + set_iir(lpr15k_0_4, ADDR_IIR_LPR_15K_0); + set_iir(lpr15k_1_4, ADDR_IIR_LPR_15K_1); + set_iir(lpr15k_2_4, ADDR_IIR_LPR_15K_2); + set_iir(lpr15k_3_4, ADDR_IIR_LPR_15K_3); + set_iir(lpr15k_4_4, ADDR_IIR_LPR_15K_4); + + set_iir(lpr15k_0_4, ADDR_IIR_LMR_15K_0); + set_iir(lpr15k_1_4, ADDR_IIR_LMR_15K_1); + set_iir(lpr15k_2_4, ADDR_IIR_LMR_15K_2); + set_iir(lpr15k_3_4, ADDR_IIR_LMR_15K_3); + set_iir(lpr15k_4_4, ADDR_IIR_LMR_15K_4); + + set_deem(0); + + adec_wr_reg(ADDR_DEMOD_GAIN, 0x22); + adec_wr_reg(ADDR_LMR_ADJ, 0x3e0); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x2e0); + + adec_wr_reg(ADDR_LPR_COMP_CTRL, 0x510); +#endif + + + adec_wr_reg((ADDR_SEL_CTRL), 0x1000); + pr_info("set eia-j done\n"); +} + +void set_nicam_dk(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_DK); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(2); + + adec_wr_reg(0x103, 0x7f); + + aa = (int)((FCLK-5.85e6)/FCLK*1024.0*1024.0*16.0); + adec_wr_reg(0x110, aa); +} + +void set_nicam_i(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_I); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.0e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(2); + adec_wr_reg(0x103, 0x7f); + + aa = (int)((FCLK-6.552e6)/FCLK*1024.0*1024.0*16.0); + adec_wr_reg(0x110, aa); +} + +void set_nicam_bg(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_BG); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(5.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(2); + adec_wr_reg(0x103, 0x7f); + + aa = (int)((FCLK-5.85e6)/FCLK*1024.0*1024.0*16.0); + adec_wr_reg(0x110, aa); +} + +void set_nicam_l(void) +{ + int aa; + + adec_wr_reg(ADDR_ADEC_CTRL, AUDIO_STANDARD_NICAM_L); + + set_filter(filter_100k, ADDR_DDC_FIR0_COEF, 65); + set_filter(filter_100k, ADDR_DDC_FIR1_COEF, 65); + + aa = (int)(6.5e6/FCLK*1024.0*1024.0*8.0); + adec_wr_reg(ADDR_DDC_FREQ0, aa); + adec_wr_reg(ADDR_LPR_GAIN_ADJ, 0x200); + + set_deem(2); + adec_wr_reg(0x103, 0x7f); + + aa = (int)((FCLK-5.85e6)/FCLK*1024.0*1024.0*16.0); + adec_wr_reg(0x110, aa); +} +static void set_standard(uint32_t standard) +{ + pr_info("\n<<<<<<<<<<<<<<< start configure register\n"); + switch (standard) { + case AUDIO_STANDARD_BTSC: + pr_info("<<<<<<<<<<<<<<< Set BTSC and Test\n"); + set_btsc(); + pr_info("<<<<<<<<<<<<<<< Set BTSC Done\n"); + break; + case AUDIO_STANDARD_A2_K: + pr_info("<<<<<<<<<<<<<<< Set A2K and Test\n"); + set_a2k(); + break; + case AUDIO_STANDARD_EIAJ: + pr_info("<<<<<<<<<<<<<<< Set EIAJ and Test\n"); + set_eiaj(); + break; + case AUDIO_STANDARD_A2_BG: + pr_info("<<<<<<<<<<<<<<< Set A2BG and Test\n"); + set_a2bg(); + break; + case AUDIO_STANDARD_A2_DK1: + pr_info("<<<<<<<<<<<<<<< Set A2 DK1 and Test\n"); + set_a2dk1(); + break; + case AUDIO_STANDARD_A2_DK2: + pr_info("<<<<<<<<<<<<<<< Set A2 DK2 and Test\n"); + set_a2dk2(); + break; + case AUDIO_STANDARD_A2_DK3: + pr_info("<<<<<<<<<<<<<<< Set A2DK3 and Test\n"); + set_a2dk3(); + break; + case AUDIO_STANDARD_NICAM_DK: + pr_info("<<<<<<<<<<<<<<< Set NICAM DK and Test\n"); + set_nicam_dk(); + break; + case AUDIO_STANDARD_NICAM_I: + pr_info("<<<<<<<<<<<<<<< Set NICAM I and Test\n"); + set_nicam_i(); + break; + case AUDIO_STANDARD_NICAM_BG: + pr_info("<<<<<<<<<<<<<<< Set NICAM BG and Test\n"); + set_nicam_bg(); + break; + case AUDIO_STANDARD_NICAM_L: + pr_info("<<<<<<<<<<<<<<< Set NICAM L and Test\n"); + set_nicam_l(); + break; + } + + pr_info("\n<<<<<<<<<<<<<<< configure register finished\n"); +} + +void update_car_power_measure(int *sc1_power, int *sc2_power) +{ + uint32_t reg_value; + + reg_value = adec_rd_reg(CARRIER_MAG_REPORT); + *sc1_power = reg_value & 0xffff; + *sc2_power = (reg_value >> 16) & 0xffff; +} + +void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag) +{ + uint32_t reg_value; + uint32_t stereo_power, dual_power; + + if (auto_en) { + reg_value = adec_rd_reg(AUDIO_MODE_REPORT); + *stereo_flag = reg_value&0x1; + *dual_flag = (reg_value>>1)&0x1; + } else { + reg_value = adec_rd_reg(POWER_REPORT); + stereo_power = reg_value & 0xffff; + dual_power = (reg_value >> 16) & 0xffff; + + if (stereo_power > dual_power && stereo_power > 0x1800) + *stereo_flag = 1; + else + *stereo_flag = 0; + + if (stereo_power < dual_power && dual_power > 0x1800) + *dual_flag = 1; + else + *dual_flag = 0; + } + +} + +void update_btsc_mode(int auto_en, int *stereo_flag, int *sap_flag) +{ + uint32_t reg_value; + uint32_t stereo_level, sap_level; + + msleep(btsc_detect_delay); + if (auto_en) { + reg_value = adec_rd_reg(AUDIO_MODE_REPORT); + *stereo_flag = reg_value&0x1; + *sap_flag = (reg_value>>1)&0x1; + } else { + reg_value = adec_rd_reg(STEREO_LEVEL_REPORT); + stereo_level = reg_value&0xffff; + + if (stereo_level > 0x1800) + *stereo_flag = 1; + else + *stereo_flag = 0; + + reg_value = adec_rd_reg(CARRIER_MAG_REPORT); + sap_level = (reg_value>>16)&0xffff; + + if (sap_level > 0x200) + *sap_flag = 1; + else + *sap_flag = 0; + } + + /*0:MONO 1:Stereo 2:MONO+SAP 3:Stereo+SAP*/ + signal_audmode = (*stereo_flag) | (*sap_flag << 1); + +} + +void update_nicam_mode(int *nicam_flag, int *nicam_mono_flag, + int *nicam_stereo_flag, int *nicam_dual_flag) +{ + uint32_t reg_value; + int nicam_lock; + int cic; + + reg_value = adec_rd_reg(0x1a3); + nicam_lock = (reg_value>>28)&1; + reg_value = adec_rd_reg(0x1a4); + cic = (reg_value>>17)&3; + + *nicam_flag = nicam_lock; + *nicam_mono_flag = (cic == 1) && nicam_lock; + *nicam_stereo_flag = (cic == 0) && nicam_lock; + *nicam_dual_flag = (cic == 2) && nicam_lock; +} + +void set_btsc_outputmode(uint32_t outmode) +{ + uint32_t reg_value; + uint32_t tmp_value, tmp_value1; + int stereo_flag, sap_flag; + + update_btsc_mode(1, &stereo_flag, &sap_flag); + reg_value = adec_rd_reg(ADDR_ADEC_CTRL); + + switch (outmode) { + case AUDIO_OUTMODE_BTSC_MONO: + tmp_value = (reg_value & 0xf) | (0 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + break; + + case AUDIO_OUTMODE_BTSC_STEREO: + if (stereo_flag) { + tmp_value = (reg_value & 0xf) | (1 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + reg_value = adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value1 = (reg_value & 0xffff); + adec_wr_reg(ADDR_LPR_COMP_CTRL, tmp_value1); + } else { + tmp_value = (reg_value & 0xf) | (0 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_BTSC_SAP: + if (sap_flag) { + if (aml_atvdemod_get_btsc_sap_mode() != 0) + tmp_value = (reg_value & 0xf) | (6 << 4); + else + tmp_value = (reg_value & 0xf) | (2 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + reg_value = adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value1 = (reg_value & 0xffff)|(1 << 16); + adec_wr_reg(ADDR_LPR_COMP_CTRL, tmp_value1); + } else if (stereo_flag) { + tmp_value = (reg_value & 0xf) | (1 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + reg_value = adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value1 = (reg_value & 0xffff); + adec_wr_reg(ADDR_LPR_COMP_CTRL, tmp_value1); + } else { + tmp_value = (reg_value & 0xf) | (0 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + } +} + +void set_a2_eiaj_outputmode(uint32_t outmode) +{ + uint32_t reg_value = 0; + uint32_t tmp_value = 0; + int stereo_flag, dual_flag; + + update_a2_eiaj_mode(1, &stereo_flag, &dual_flag); + reg_value = adec_rd_reg(ADDR_ADEC_CTRL); + + switch (outmode) { + case AUDIO_OUTMODE_A2_MONO: + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + break; + + case AUDIO_OUTMODE_A2_STEREO: + if (stereo_flag) { + tmp_value = (reg_value&0xf)|(1<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_A2_DUAL_A: + if (stereo_flag) { + tmp_value = (reg_value&0xf)|(1<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else if (dual_flag) { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_A2_DUAL_B: + if (stereo_flag) { + tmp_value = (reg_value&0xf)|(1<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else if (dual_flag) { + tmp_value = (reg_value&0xf)|(2<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_A2_DUAL_AB: + if (stereo_flag) { + tmp_value = (reg_value&0xf)|(1<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else if (dual_flag) { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + } +} + +void set_nicam_outputmode(uint32_t outmode) +{ + uint32_t reg_value = 0; + uint32_t tmp_value = 0; + int nicam_mono_flag, nicam_stereo_flag, nicam_dual_flag; + int nicam_lock; + + update_nicam_mode(&nicam_lock, &nicam_mono_flag, + &nicam_stereo_flag, &nicam_dual_flag); + + reg_value = adec_rd_reg(ADDR_ADEC_CTRL); + pr_info("%s nicam_lock:%d, regval:0x%x\n", + __func__, nicam_lock, reg_value); + switch (outmode) { + case AUDIO_OUTMODE_NICAM_MONO: + if (nicam_lock) { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_NICAM_MONO1: + if (nicam_lock) { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_NICAM_STEREO: + if (nicam_lock && nicam_stereo_flag) { + tmp_value = (reg_value&0xf)|(1<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else if (nicam_lock && !nicam_stereo_flag) { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_NICAM_DUAL_A: + if (nicam_lock) { + tmp_value = (reg_value&0xf)|(0<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_NICAM_DUAL_B: + if (nicam_lock) { + tmp_value = (reg_value&0xf)|(2<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_NICAM_DUAL_AB: + if (nicam_lock) { + tmp_value = (reg_value&0xf)|(1<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } else { + tmp_value = (reg_value&0xf)|(3<<4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + } + pr_info("%s tmp_value :0x%x\n", __func__, reg_value); +} + +void set_outputmode(uint32_t standard, uint32_t outmode) +{ +#ifdef AUDIO_MOD_DET_INTERNAL + uint32_t tmp_value = 0; + uint32_t reg_value = 0; + + reg_value = adec_rd_reg(ADDR_ADEC_CTRL); + tmp_value = (reg_value&0xf)|(outmode<<4)|(1<<6); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + pr_info("set_outputmode:std:%d, outmod:%d\n", standard, outmode); + if (standard == AUDIO_STANDARD_BTSC && + outmode == AUDIO_OUTMODE_SAP_DUAL) { + reg_value = adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value = (reg_value & 0xffff)|(1 << 16); + adec_wr_reg(ADDR_LPR_COMP_CTRL, tmp_value); + } + + if (standard == AUDIO_STANDARD_NICAM_DK || + standard == AUDIO_STANDARD_NICAM_I || + standard == AUDIO_STANDARD_NICAM_BG || + standard == AUDIO_STANDARD_NICAM_L) { + pr_info("set_outputmode NICAM...\n"); + set_nicam_outputmode(outmode); + } + +#else + switch (standard) { + case AUDIO_STANDARD_BTSC: + set_btsc_outputmode(outmode); + break; + case AUDIO_STANDARD_A2_K: + case AUDIO_STANDARD_EIAJ: + case AUDIO_STANDARD_A2_BG: + case AUDIO_STANDARD_A2_DK1: + case AUDIO_STANDARD_A2_DK2: + case AUDIO_STANDARD_A2_DK3: + set_a2_eiaj_outputmode(outmode); + break; + case AUDIO_STANDARD_NICAM_DK: + case AUDIO_STANDARD_NICAM_I: + case AUDIO_STANDARD_NICAM_BG: + case AUDIO_STANDARD_NICAM_L: + set_nicam_outputmode(outmode); + break; + } +#endif +} + +void aud_demod_clk_gate(int on) +{ + if (on) + adec_wr_reg(1, 0xf13); + else + adec_wr_reg(1, 0); +} + +void configure_adec(int Audio_mode) +{ + pr_info("configure audio demod register\n"); + + aud_demod_clk_gate(1); + + /* + * set gate clk for btsc and nicam . + */ + if (is_meson_txhd_cpu()) + adec_wr_reg(0x28, 0xa); + + set_standard(Audio_mode); + + set_general(); + set_i2s_intrp(0); +} + +void adec_soft_reset(void) +{ + adec_wr_reg(ADEC_RESET, 0x0); + adec_wr_reg(ADEC_RESET, 0x1); +} + +void audio_thd_init(void) +{ + adec_wr_reg(CNT_MAX0, 0x6f2a9); + adec_wr_reg(THD_OV0, 0x18000); + thd_flag = 0; + thd_tmp_v = 0; + thd_cnt = 0; +} + +void audio_thd_det(void) +{ + thd_cnt++; + if (thd_cnt % 5 != 0) + return; + + if (thd_flag == 0) { + thd_tmp_v += adec_rd_reg(OV_CNT_REPORT) & 0xffff; + + pr_info("#0x12:0x%x\n", (adec_rd_reg(OV_CNT_REPORT) & 0xffff)); + if (thd_cnt == 15) { + thd_tmp_v /= 3; + if (thd_tmp_v > audio_thd_threshold1) { + thd_flag = 1; + adec_wr_reg(ADDR_DEMOD_GAIN, 0x13); + } + thd_cnt = 0; + thd_tmp_v = 0; + } + } else if (thd_flag == 1) { + thd_tmp_v += adec_rd_reg(OV_CNT_REPORT) & 0xffff; + + pr_info("#0x13:0x%x\n", (adec_rd_reg(OV_CNT_REPORT) & 0xffff)); + if (thd_cnt == 15) { + thd_tmp_v /= 3; + if (thd_tmp_v <= audio_thd_threshold2) { + thd_flag = 0; + adec_wr_reg(ADDR_DEMOD_GAIN, 0x12); + } + thd_cnt = 0; + thd_tmp_v = 0; + } + } +} + +void audio_mode_det(int mode) +{ + if (is_atvdemod_work() && + (is_meson_txlx_cpu() || is_meson_txhd_cpu())) { + uint32_t reg_value; + uint32_t tmp_value, tmp_value1; + int stereo_flag, sap_flag; + static int last_stereo_flag = -1, last_sap_flag = -1; + + reg_value = adec_rd_reg(AUDIO_MODE_REPORT); + stereo_flag = reg_value&0x1; + sap_flag = (reg_value>>1)&0x1; + reg_value = adec_rd_reg(ADDR_ADEC_CTRL); + + if (sap_flag != last_sap_flag + || stereo_flag != last_stereo_flag) { + switch (mode) { + case AUDIO_OUTMODE_BTSC_MONO: + tmp_value = (reg_value & 0xf)|(0 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + break; + + case AUDIO_OUTMODE_BTSC_STEREO: + if (stereo_flag) { + tmp_value = (reg_value & 0xf)|(1 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + reg_value = + adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value1 = (reg_value & 0xffff); + adec_wr_reg(ADDR_LPR_COMP_CTRL, + tmp_value1); + } else { + tmp_value = (reg_value & 0xf)|(0 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + + case AUDIO_OUTMODE_BTSC_SAP: + if (sap_flag) { + tmp_value = (reg_value & 0xf)|(6 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + reg_value = + adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value1 = + (reg_value & 0xffff)|(1 << 16); + adec_wr_reg(ADDR_LPR_COMP_CTRL, + tmp_value1); + } else if (stereo_flag) { + tmp_value = (reg_value & 0xf)|(1 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + + reg_value = + adec_rd_reg(ADDR_LPR_COMP_CTRL); + tmp_value1 = (reg_value & 0xffff); + adec_wr_reg(ADDR_LPR_COMP_CTRL, + tmp_value1); + } else { + tmp_value = (reg_value & 0xf)|(0 << 4); + adec_wr_reg(ADDR_ADEC_CTRL, tmp_value); + } + break; + } + } + + last_stereo_flag = stereo_flag; + last_sap_flag = sap_flag; + + pr_info("[tuner..] atvdemod_monitor_audio done ....\n"); + } +} + +#endif /* __ATVAUDDEMOD_FUN_H */ diff --git a/drivers/amlogic/atv_demod/atvauddemod_func.h b/drivers/amlogic/atv_demod/atvauddemod_func.h new file mode 100644 index 000000000000..4febf74b1bfa --- /dev/null +++ b/drivers/amlogic/atv_demod/atvauddemod_func.h @@ -0,0 +1,32 @@ +/* atvauddemod_func.h */ +#ifndef __ATVAUDDEMOD_H_ +#define __ATVAUDDEMOD_H_ + +#include "aud_demod_reg.h" + + +extern int atvaudiodem_reg_read(unsigned int reg, unsigned int *val); +extern int atvaudiodem_reg_write(unsigned int reg, unsigned int val); +extern uint32_t adec_rd_reg(uint32_t addr); +extern void adec_wr_reg(uint32_t reg, uint32_t val); +extern int is_atvdemod_work(void); +int get_atvdemod_state(void); +void set_atvdemod_state(int state); +extern int aml_atvdemod_get_btsc_sap_mode(void); +extern void audio_mode_det(int mode); + +void set_outputmode(uint32_t standard, uint32_t outmode); +void aud_demod_clk_gate(int on); +void configure_adec(int Audio_mode); +void adec_soft_reset(void); +void audio_thd_init(void); +void audio_thd_det(void); +void set_nicam_outputmode(uint32_t outmode); +void set_a2_eiaj_outputmode(uint32_t outmode); +void set_btsc_outputmode(uint32_t outmode); +void update_nicam_mode(int *nicam_flag, int *nicam_mono_flag, + int *nicam_stereo_flag, int *nicam_dual_flag); +void update_btsc_mode(int auto_en, int *stereo_flag, int *sap_flag); +void update_a2_eiaj_mode(int auto_en, int *stereo_flag, int *dual_flag); + +#endif /* __ATVAUDDEMOD_H_ */ diff --git a/drivers/amlogic/atv_demod/atvdemod_func.c b/drivers/amlogic/atv_demod/atvdemod_func.c new file mode 100644 index 000000000000..725c37489b36 --- /dev/null +++ b/drivers/amlogic/atv_demod/atvdemod_func.c @@ -0,0 +1,2440 @@ +/* + * Silicon labs amlogic Atvdemod Device Driver + * + * Author: dezhi kong + * + * + * Copyright (C) 2014 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/* Standard Liniux Headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.h" + +#include "atvdemod_func.h" +#include "atv_demod_debug.h" +#include "atv_demod_driver.h" +#include "atvauddemod_func.h" +#include "atv_demod_ops.h" +#include "atv_demod_driver.h" + +static int broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC; +module_param(broad_std, int, 0644); +MODULE_PARM_DESC(broad_std, "\n broad_std\n"); + +int aud_std = AUDIO_STANDARD_NICAM_DK; +module_param(aud_std, int, 0644); +MODULE_PARM_DESC(aud_std, "\n audio std\n"); + +int aud_mode = AUDIO_OUTMODE_STEREO; +module_param(aud_mode, int, 0644); +MODULE_PARM_DESC(aud_mode, "\n audio demod output mode val\n"); + +int aud_auto = 1; +module_param(aud_auto, int, 0644); +MODULE_PARM_DESC(aud_auto, "\n audio demod auto detec\n"); + +static unsigned long over_threshold = 0xffff; +module_param(over_threshold, ulong, 0644); +MODULE_PARM_DESC(over_threshold, "\n over_threshold\n"); + +static unsigned long input_amplitude = 0xffff; +module_param(input_amplitude, ulong, 0644); +MODULE_PARM_DESC(input_amplitude, "\n input_amplitude\n"); + +static bool audio_det_en; +module_param(audio_det_en, bool, 0644); +MODULE_PARM_DESC(audio_det_en, "\n audio_det_en\n"); + +static int non_std_en; +module_param(non_std_en, int, 0644); +MODULE_PARM_DESC(non_std_en, "\n non_std_en\n"); + +static int atv_video_gain; +module_param(atv_video_gain, int, 0644); +MODULE_PARM_DESC(atv_video_gain, "\n atv_video_gain reg:0x0f44\n"); + +static int carrier_amplif_val = 0xc030901; +module_param(carrier_amplif_val, int, 0644); +MODULE_PARM_DESC(carrier_amplif_val, "\ncarrier_amplif_val (reg 0x0624)\n"); + +static int extra_input_fil_val = 0x1030501; +module_param(extra_input_fil_val, int, 0644); +MODULE_PARM_DESC(extra_input_fil_val, "\nextra_input_fil_val (reg 0x0900)\n"); + +static int audio_det_mode = AUDIO_AUTO_DETECT; +module_param(audio_det_mode, int, 0644); +MODULE_PARM_DESC(audio_det_mode, "\n audio_det_mode\n"); + +static int aud_dmd_jilinTV; +module_param(aud_dmd_jilinTV, int, 0644); +MODULE_PARM_DESC(aud_dmd_jilinTV, "\naud dmodulation setting for jilin TV\n"); + +static unsigned int if_freq = 4250000; /*PAL-DK:3250000;NTSC-M:4250000*/ +module_param(if_freq, uint, 0644); +MODULE_PARM_DESC(if_freq, "\n if_freq\n"); + +static int if_inv; +module_param(if_inv, int, 0644); +MODULE_PARM_DESC(if_inv, "\n if_inv\n"); + +static int afc_default = CARR_AFC_DEFAULT_VAL; +module_param(afc_default, int, 0644); +MODULE_PARM_DESC(afc_default, "\n afc_default\n"); + +/* + * GDE_Curve + * 0: CURVE-M + * 1: CURVE-A + * 2: CURVE-B + * 3: CURVE-CHINA + * 4: BYPASS + * BG --> CURVE-B(BYPASS) + * DK --> CURVE-CHINA + * NM --> CURVE-M + * I --> BYPASS + * SECAM --> BYPASS + */ +static int gde_curve; +module_param(gde_curve, int, 0644); +MODULE_PARM_DESC(gde_curve, "\n gde_curve\n"); + +static int sound_format; +module_param(sound_format, int, 0644); +MODULE_PARM_DESC(sound_format, "\n sound_format\n"); + +static unsigned int freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; +module_param(freq_hz_cvrt, int, 0644); +MODULE_PARM_DESC(freq_hz_cvrt, "\n freq_hz\n"); + +int atvdemod_debug_en; +module_param(atvdemod_debug_en, int, 0644); +MODULE_PARM_DESC(atvdemod_debug_en, "\n atvdemod_debug_en\n"); + +/*1:gpio mode output low;2:pwm mode*/ +static unsigned int atvdemod_agc_pinmux = 2; +module_param(atvdemod_agc_pinmux, int, 0644); +MODULE_PARM_DESC(atvdemod_agc_pinmux, "\n atvdemod_agc_pinmux\n"); + +static unsigned int atvdemod_afc_range = 5; +module_param(atvdemod_afc_range, uint, 0644); +MODULE_PARM_DESC(atvdemod_afc_range, "\n atvdemod_afc_range\n"); + +static unsigned int atvdemod_afc_offset = 500; +module_param(atvdemod_afc_offset, uint, 0644); +MODULE_PARM_DESC(atvdemod_afc_offset, "\n atvdemod_afc_offset\n"); + +static unsigned int atvdemod_timer_en = 1; +module_param(atvdemod_timer_en, uint, 0644); +MODULE_PARM_DESC(atvdemod_timer_en, "\n atvdemod_timer_en\n"); + +static unsigned int atvdemod_afc_en; +module_param(atvdemod_afc_en, uint, 0644); +MODULE_PARM_DESC(atvdemod_afc_en, "\n atvdemod_afc_en\n"); + +static unsigned int atvdemod_monitor_en; +module_param(atvdemod_monitor_en, uint, 0644); +MODULE_PARM_DESC(atvdemod_monitor_en, "\n atvdemod_monitor_en\n"); + +static unsigned int atvdemod_det_snr_en = 1; +module_param(atvdemod_det_snr_en, uint, 0644); +MODULE_PARM_DESC(atvdemod_det_snr_en, "\n atvdemod_det_snr_en\n"); + +static unsigned int audio_thd_en = 1; +module_param(audio_thd_en, uint, 0644); +MODULE_PARM_DESC(audio_thd_en, "\n audio_thd_en\n"); + +static unsigned int pwm_kp = 0x19; +module_param(pwm_kp, uint, 0644); +MODULE_PARM_DESC(pwm_kp, "\n pwm_kp\n"); + +static unsigned int reg_dbg_en; +module_param(reg_dbg_en, uint, 0644); +MODULE_PARM_DESC(reg_dbg_en, "\n reg_dbg_en\n"); + +static unsigned int audio_gain_val = 512; +module_param(audio_gain_val, uint, 0644); +MODULE_PARM_DESC(audio_gain_val, "\n audio_gain_val\n"); + +static unsigned int audio_a2_threshold = 0x800; +module_param(audio_a2_threshold, uint, 0644); +MODULE_PARM_DESC(audio_a2_threshold, "\n audio_a2_threshold\n"); + +static unsigned int audio_a2_delay = 10; +module_param(audio_a2_delay, uint, 0644); +MODULE_PARM_DESC(audio_a2_delay, "\n audio_a2_delay\n"); + + +enum AUDIO_SCAN_ID { + ID_PAL_I = 0, + ID_PAL_M, + ID_PAL_DK, + ID_PAL_BG, + ID_MAX, +}; + +static unsigned int mix1_freq; +static unsigned int timer_init_flag; +struct timer_list atvdemod_timer; +static int snr_val; +int broad_std_except_pal_m; + +int get_atvdemod_snr_val(void) +{ + return snr_val; +} +//EXPORT_SYMBOL(get_atvdemod_snr_val); + +void amlatvdemod_set_std(int val) +{ + broad_std = val; +} +//EXPORT_SYMBOL(amlatvdemod_set_std); + +void atv_dmd_wr_reg(unsigned char block, unsigned char reg, unsigned long data) +{ + /* unsigned long data_tmp; */ + unsigned long reg_addr = (block<<8) + reg * 4; + + amlatvdemod_reg_write(reg_addr, data); +} + +unsigned long atv_dmd_rd_reg(unsigned char block, unsigned char reg) +{ + unsigned long data = 0; + unsigned long reg_addr = (block<<8) + reg * 4; + + amlatvdemod_reg_read(reg_addr, (unsigned int *)&data); + return data; +} + +unsigned long atv_dmd_rd_byte(unsigned long block_addr, unsigned long reg_addr) +{ + unsigned long data; + + data = atv_dmd_rd_long(block_addr, reg_addr); + /*R_APB_REG((((block_addr & 0xff) <<6) + */ + /* ((reg_addr & 0xff) >>2)) << 2);*/ + /*((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+*/ + /*((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2)));*/ + if ((reg_addr & 0x3) == 0) + data = data >> 24; + else if ((reg_addr & 0x3) == 1) + data = (data >> 16 & 0xff); + else if ((reg_addr & 0x3) == 2) + data = (data >> 8 & 0xff); + else if ((reg_addr & 0x3) == 3) + data = (data >> 0 & 0xff); + return data; +} + +unsigned long atv_dmd_rd_word(unsigned long block_addr, unsigned long reg_addr) +{ + unsigned long data; + + data = atv_dmd_rd_long(block_addr, reg_addr); + /*R_APB_REG((((block_addr & 0xff) <<6) + */ + /*((reg_addr & 0xff) >>2)) << 2);*/ + /*((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+*/ + /*((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2)));*/ + if ((reg_addr & 0x3) == 0) + data = data >> 16; + else if ((reg_addr & 0x3) == 1) + data = (data >> 8 & 0xffff); + else if ((reg_addr & 0x3) == 2) + data = (data >> 0 & 0xffff); + else if ((reg_addr & 0x3) == 3) + data = (((data & 0xff) << 8) | ((data >> 24) & 0xff)); + return data; +} + +unsigned long atv_dmd_rd_long(unsigned long block_addr, unsigned long reg_addr) +{ + unsigned long data; + /*data = *((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+*/ + /*((((block_addr & 0xff) <<6) + ((reg_addr & 0xff) >>2)) << 2)));*/ + data = + R_ATVDEMOD_REG((((block_addr & 0xff) << 6) + + ((reg_addr & 0xff) >> 2)) << 2); + + return data; +} +//EXPORT_SYMBOL(atv_dmd_rd_long); + +void atv_dmd_wr_long(unsigned long block_addr, unsigned long reg_addr, + unsigned long data) +{ + W_ATVDEMOD_REG((((block_addr & 0xff) << 6) + + ((reg_addr & 0xff) >> 2)) << 2, data); + if (reg_dbg_en) + pr_dbg("block_addr:0x%x,reg_addr:0x%x;data:0x%x\n", + (unsigned int)block_addr, (unsigned int)reg_addr, + (unsigned int)data); + /**((volatile unsigned long *)*/ + /*(ATV_DMD_APB_BASE_ADDR+((((block_addr & 0xff) << 6) +*/ + /*((reg_addr & 0xff) >> 2)) << 2))) = data;*/ + +} +//EXPORT_SYMBOL(atv_dmd_wr_long); + +void atv_dmd_wr_word(unsigned long block_addr, unsigned long reg_addr, + unsigned long data) +{ + unsigned long data_tmp; + + data_tmp = atv_dmd_rd_long(block_addr, reg_addr); + data = data & 0xffff; + if ((reg_addr & 0x3) == 0) + data = (data << 16 | (data_tmp & 0xffff)); + else if ((reg_addr & 0x3) == 1) + data = + ((data_tmp & 0xff000000) | (data << 8) | (data_tmp & 0xff)); + else if ((reg_addr & 0x3) == 2) + data = (data | (data_tmp & 0xffff0000)); + else if ((reg_addr & 0x3) == 3) + data = + (((data & 0xff) << 24) | ((data_tmp & 0xffff0000) >> 8) | + ((data & 0xff00) >> 8)); + + /**((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+*/ + /*((((block_addr & 0xff) <<6) + */ + /*((reg_addr & 0xff) >>2)) << 2))) = data;*/ + atv_dmd_wr_long(block_addr, reg_addr, data); + /*W_ATVDEMOD_REG(((((block_addr & 0xff) <<6) +*/ + /*((reg_addr & 0xff) >>2)) << 2), data);*/ + +} + +void atv_dmd_wr_byte(unsigned long block_addr, unsigned long reg_addr, + unsigned long data) +{ + unsigned long data_tmp; + + data_tmp = atv_dmd_rd_long(block_addr, reg_addr); + + /*pr_info("atv demod wr byte, read block addr %lx\n",block_addr);*/ + /*pr_info("atv demod wr byte, read reg addr %lx\n", reg_addr);*/ + /*pr_info("atv demod wr byte, wr data %lx\n",data);*/ + /*pr_info("atv demod wr byte, read data out %lx\n",data_tmp);*/ + + data = data & 0xff; + /*pr_info("atv demod wr byte, data & 0xff %lx\n",data);*/ + if ((reg_addr & 0x3) == 0) { + data = (data << 24 | (data_tmp & 0xffffff)); + /*pr_info("atv demod wr byte, reg_addr & 0x3 == 0,*/ + /*wr data %lx\n",data);*/ + } else if ((reg_addr & 0x3) == 1) + data = + ((data_tmp & 0xff000000) | (data << 16) | + (data_tmp & 0xffff)); + else if ((reg_addr & 0x3) == 2) + data = + ((data_tmp & 0xffff0000) | (data << 8) | (data_tmp & 0xff)); + else if ((reg_addr & 0x3) == 3) + data = ((data_tmp & 0xffffff00) | (data & 0xff)); + + /*pr_info("atv demod wr byte, wr data %lx\n",data);*/ + + /**((volatile unsigned long *) (ATV_DMD_APB_BASE_ADDR+*/ + /*((((block_addr & 0xff) <<6) + */ + /*((reg_addr & 0xff) >>2)) << 2))) = data;*/ + atv_dmd_wr_long(block_addr, reg_addr, data); + /*W_ATVDEMOD_REG(((((block_addr & 0xff) <<6) +*/ + /*((reg_addr & 0xff) >>2)) << 2), data);*/ +} + +void set_audio_gain_val(int val) +{ + audio_gain_val = val; +} + +void set_video_gain_val(int val) +{ + atv_video_gain = val; +} + +void atv_dmd_soft_reset(void) +{ + atv_dmd_wr_long(0x1d, 0x0, 0x1035);/* disable dac */ + atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x0); + atv_dmd_wr_byte(APB_BLOCK_ADDR_SYSTEM_MGT, 0x0, 0x1); + atv_dmd_wr_long(0x1d, 0x0, 0x1037);/* enable dac */ +} + +void atv_dmd_input_clk_32m(void) +{ + atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_MGR, 0x2, 0x1); +} + +void read_version_register(void) +{ + unsigned long data, Byte1, Byte2, Word; + + pr_info("ATV-DMD read version register\n"); + Byte1 = atv_dmd_rd_byte(APB_BLOCK_ADDR_VERS_REGISTER, 0x0); + Byte2 = atv_dmd_rd_byte(APB_BLOCK_ADDR_VERS_REGISTER, 0x1); + Word = atv_dmd_rd_word(APB_BLOCK_ADDR_VERS_REGISTER, 0x2); + data = atv_dmd_rd_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0); + + pr_info("atv demod read version register data out %lx\n", data); + + if ((data != 0x516EAB13) + || (((Byte1 << 24) | (Byte2 << 16) | Word) != 0x516EAB13)) + pr_info("atv demod read version reg failed\n"); +} + +void check_communication_interface(void) +{ + unsigned long data_tmp; + + pr_info("ATV-DMD check communication intf\n"); + atv_dmd_wr_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0, 0xA1B2C3D4); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VERS_REGISTER, 0x1, 0x34); + atv_dmd_wr_word(APB_BLOCK_ADDR_VERS_REGISTER, 0x2, 0xBCDE); + data_tmp = atv_dmd_rd_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0); + pr_info("atv demod check communication intf data out %lx\n", data_tmp); + + if (data_tmp != 0xa134bcde) + pr_info("atv demod check communication intf failed\n"); + atv_dmd_wr_long(APB_BLOCK_ADDR_VERS_REGISTER, 0x0, 0x516EAB13); +} + +void power_on_receiver(void) +{ + atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_MGR, 0x2, 0x11); +} + +void atv_dmd_misc(void) +{ + atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x38); /*zhuangwei*/ + /*cpu.write_byte(8'h1A,8'h0E,8'h06);//zhuangwei*/ + /*cpu.write_byte(8'h19,8'h01,8'h7f);//zhuangwei*/ + atv_dmd_wr_byte(0x0f, 0x45, 0x90); /*zhuangwei*/ + + atv_dmd_wr_long(0x0f, 0x44, 0x5c8808c1);/*zhuangwei*/ + if (amlatvdemod_devp->tuner_id == AM_TUNER_R840) { + atv_dmd_wr_long(0x0f, 0x3c, reg_23cf);/*zhuangwei*/ + /*guanzhong@20150804a*/ + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x00, 0x1); + if (is_meson_txhd_cpu()) { + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, + 0x10, 0x00011020); + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, + 0x08, 0x3d170200); + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, + 0x14, 0x01010855); + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, + 0x1C, 0x03010855); + } else { + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, + 0x08, 0x601b0201); + } + /*dezhi@20150610a 0x1a maybe better?!*/ + /* atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0x19); */ + } else { + atv_dmd_wr_long(0x0f, 0x3c, 0x88188832);/*zhuangwei*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46170200); + } + + if (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661) { + atv_dmd_wr_long(0x0c, 0x04, 0xbffa0000) ;/*test in sky*/ + atv_dmd_wr_long(0x0c, 0x00, 0x6f4000);/*test in sky*/ + /*guanzhong@20151013 fix nonstd def is:0x0c010301;0x0c020601*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c030901); + } else { + /*zhuangwei 0xdafa0000*/ + atv_dmd_wr_long(0x0c, 0x04, 0xc8fa0000); + atv_dmd_wr_long(0x0c, 0x00, 0x554000);/*zhuangwei*/ + } + atv_dmd_wr_long(0x19, 0x04, 0xdafa0000);/*zhuangwei*/ + atv_dmd_wr_long(0x19, 0x00, 0x4a4000);/*zhuangwei*/ + /*atv_dmd_wr_byte(0x0c,0x01,0x28);//pwd-out gain*/ + /*atv_dmd_wr_byte(0x0c,0x04,0xc0);//pwd-out offset*/ + + aml_audio_valume_gain_set(audio_gain_val); + /* 20160121 fix audio demodulation over */ + atv_dmd_wr_long(0x09, 0x00, 0x1030501); + atv_dmd_wr_long(0x09, 0x04, 0x1900000); + if (aud_dmd_jilinTV) + atv_dmd_wr_long(0x09, 0x00, 0x2030503); + if (non_std_en == 1) { + atv_dmd_wr_long(0x09, 0x00, 0x2030503); + atv_dmd_wr_long(0x0f, 0x44, 0x7c8808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0x0c010801); + } else if (non_std_en == 2) { + /* fix vsync signal is too weak */ + atv_dmd_wr_long(0x09, 0x00, 0x1030501); + atv_dmd_wr_long(0x0f, 0x44, 0x8c0808c1); + atv_dmd_wr_long(0x0f, 0x0c, 0x387c0831); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, 0xc030901); + } else { + atv_dmd_wr_long(0x09, 0x00, extra_input_fil_val); + if (atv_video_gain) + atv_dmd_wr_long(0x0f, 0x44, atv_video_gain); + else + atv_dmd_wr_long(0x0f, 0x44, 0xfc0808c1); + atv_dmd_wr_long(APB_BLOCK_ADDR_CARR_RCVY, 0x24, + carrier_amplif_val); + } + +} + +/*Broadcast_Standard*/ +/* 0: NTSC*/ +/* 1: NTSC-J*/ +/* 2: PAL-M,*/ +/* 3: PAL-BG*/ +/* 4: DTV*/ +/* 5: SECAM- DK2*/ +/* 6: SECAM -DK3*/ +/* 7: PAL-BG, NICAM*/ +/* 8: PAL-DK-CHINA*/ +/* 9: SECAM-L / SECAM-DK3*/ +/* 10: PAL-I*/ +/* 11: PAL-DK1*/ +/*GDE_Curve*/ +/* 0: CURVE-M*/ +/* 1: CURVE-A*/ +/* 2: CURVE-B*/ +/* 3: CURVE-CHINA*/ +/* 4: BYPASS*/ +/*sound format 0: MONO;1:NICAM*/ +void configure_receiver(int Broadcast_Standard, unsigned int Tuner_IF_Frequency, + int Tuner_Input_IF_inverted, int GDE_Curve, + int sound_format) +{ + int tmp_int; + int mixer1 = 0; + int mixer3 = 0; + int mixer3_bypass = 0; + int cv = 0; + /*int if_freq = 0;*/ + + int i = 0; + int super_coef0 = 0; + int super_coef1 = 0; + int super_coef2 = 0; + int gp_coeff_1[37]; + int gp_coeff_2[37]; + int gp_cv_g1 = 0; + int gp_cv_g2 = 0; + int crvy_reg_1 = 0; + int crvy_reg_2 = 0; + int sif_co_mx = 0; + int sif_fi_mx = 0; + int sif_ic_bw = 0; + int sif_bb_bw = 0; + int sif_deemp = 0; + int sif_cfg_demod = 0; + int sif_fm_gain = 0; + int gd_coeff[6]; + int gd_bypass; + + pr_info("ATV-DMD configure receiver register\n"); + + if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I)) { + gp_coeff_1[0] = 0x57777; + gp_coeff_1[1] = 0xdd777; + gp_coeff_1[2] = 0x7d777; + gp_coeff_1[3] = 0x75777; + gp_coeff_1[4] = 0x75777; + gp_coeff_1[5] = 0x7c777; + gp_coeff_1[6] = 0x5c777; + gp_coeff_1[7] = 0x44777; + gp_coeff_1[8] = 0x54777; + gp_coeff_1[9] = 0x47d77; + gp_coeff_1[10] = 0x55d77; + gp_coeff_1[11] = 0x55577; + gp_coeff_1[12] = 0x77577; + gp_coeff_1[13] = 0xc4c77; + gp_coeff_1[14] = 0xd7d77; + gp_coeff_1[15] = 0x75477; + gp_coeff_1[16] = 0xcc477; + gp_coeff_1[17] = 0x575d7; + gp_coeff_1[18] = 0xc4c77; + gp_coeff_1[19] = 0xdd757; + gp_coeff_1[20] = 0xdd477; + gp_coeff_1[21] = 0x77dd7; + gp_coeff_1[22] = 0x5dc77; + gp_coeff_1[23] = 0x47c47; + gp_coeff_1[24] = 0x57477; + gp_coeff_1[25] = 0x5c7c7; + gp_coeff_1[26] = 0xccc77; + gp_coeff_1[27] = 0x5ddd5; + gp_coeff_1[28] = 0x54477; + gp_coeff_1[29] = 0x7757d; + gp_coeff_1[30] = 0x755d7; + gp_coeff_1[31] = 0x47cc4; + gp_coeff_1[32] = 0x57d57; + gp_coeff_1[33] = 0x554cc; + gp_coeff_1[34] = 0x755d7; + gp_coeff_1[35] = 0x7d3b2; + gp_coeff_1[36] = 0x73a91; + gp_coeff_2[0] = 0xd5777; + gp_coeff_2[1] = 0x77777; + gp_coeff_2[2] = 0x7c777; + gp_coeff_2[3] = 0xcc777; + gp_coeff_2[4] = 0xc7777; + gp_coeff_2[5] = 0xdd777; + gp_coeff_2[6] = 0x44c77; + gp_coeff_2[7] = 0x54c77; + gp_coeff_2[8] = 0xdd777; + gp_coeff_2[9] = 0x7c777; + gp_coeff_2[10] = 0xc7c77; + gp_coeff_2[11] = 0x75c77; + gp_coeff_2[12] = 0xdd577; + gp_coeff_2[13] = 0x44777; + gp_coeff_2[14] = 0xd5c77; + gp_coeff_2[15] = 0xdc777; + gp_coeff_2[16] = 0xd7757; + gp_coeff_2[17] = 0x4c757; + gp_coeff_2[18] = 0x7d777; + gp_coeff_2[19] = 0x75477; + gp_coeff_2[20] = 0x57547; + gp_coeff_2[21] = 0xdc747; + gp_coeff_2[22] = 0x74777; + gp_coeff_2[23] = 0x75757; + gp_coeff_2[24] = 0x4cc75; + gp_coeff_2[25] = 0xd4747; + gp_coeff_2[26] = 0x7d7d7; + gp_coeff_2[27] = 0xd5577; + gp_coeff_2[28] = 0xc4c75; + gp_coeff_2[29] = 0xcc477; + gp_coeff_2[30] = 0xdd54c; + gp_coeff_2[31] = 0x7547d; + gp_coeff_2[32] = 0x55547; + gp_coeff_2[33] = 0x5575c; + gp_coeff_2[34] = 0xd543a; + gp_coeff_2[35] = 0x57b3a; + gp_coeff_2[36] = 0x77777; + gp_cv_g1 = 0x2b062d; + gp_cv_g2 = 0x40fa2d; + } else if ((Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG_NICAM)) { + gp_coeff_1[0] = 0x75777; + gp_coeff_1[1] = 0x57777; + gp_coeff_1[2] = 0x7d777; + gp_coeff_1[3] = 0x75777; + gp_coeff_1[4] = 0x75777; + gp_coeff_1[5] = 0x7c777; + gp_coeff_1[6] = 0x47777; + gp_coeff_1[7] = 0x74777; + gp_coeff_1[8] = 0xd5d77; + gp_coeff_1[9] = 0xc7777; + gp_coeff_1[10] = 0x77577; + gp_coeff_1[11] = 0xd7d77; + gp_coeff_1[12] = 0x75d77; + gp_coeff_1[13] = 0xdd477; + gp_coeff_1[14] = 0x77d77; + gp_coeff_1[15] = 0x75c77; + gp_coeff_1[16] = 0xc4477; + gp_coeff_1[17] = 0x4c777; + gp_coeff_1[18] = 0x5d5d7; + gp_coeff_1[19] = 0xd7d57; + gp_coeff_1[20] = 0x47577; + gp_coeff_1[21] = 0xd7dd7; + gp_coeff_1[22] = 0xd7d57; + gp_coeff_1[23] = 0xdd757; + gp_coeff_1[24] = 0xc75c7; + gp_coeff_1[25] = 0x7d477; + gp_coeff_1[26] = 0x5d747; + gp_coeff_1[27] = 0x7ddc7; + gp_coeff_1[28] = 0xc4c77; + gp_coeff_1[29] = 0xd4c75; + gp_coeff_1[30] = 0xc755d; + gp_coeff_1[31] = 0x47cc7; + gp_coeff_1[32] = 0xdd7d4; + gp_coeff_1[33] = 0x4c75d; + gp_coeff_1[34] = 0xc7dcc; + gp_coeff_1[35] = 0xd52a2; + gp_coeff_1[36] = 0x555a1; + gp_coeff_2[0] = 0x5d777; + gp_coeff_2[1] = 0x47777; + gp_coeff_2[2] = 0x7d777; + gp_coeff_2[3] = 0xcc777; + gp_coeff_2[4] = 0xd7777; + gp_coeff_2[5] = 0x7c777; + gp_coeff_2[6] = 0x7dd77; + gp_coeff_2[7] = 0xdd777; + gp_coeff_2[8] = 0x7c777; + gp_coeff_2[9] = 0x57c77; + gp_coeff_2[10] = 0x7c777; + gp_coeff_2[11] = 0xd5777; + gp_coeff_2[12] = 0xd7c77; + gp_coeff_2[13] = 0xdd777; + gp_coeff_2[14] = 0x77477; + gp_coeff_2[15] = 0xc7d77; + gp_coeff_2[16] = 0xc4777; + gp_coeff_2[17] = 0x57557; + gp_coeff_2[18] = 0xd5577; + gp_coeff_2[19] = 0xd5577; + gp_coeff_2[20] = 0x7d547; + gp_coeff_2[21] = 0x74757; + gp_coeff_2[22] = 0xc7577; + gp_coeff_2[23] = 0xcc7d5; + gp_coeff_2[24] = 0x4c747; + gp_coeff_2[25] = 0xddc77; + gp_coeff_2[26] = 0x54447; + gp_coeff_2[27] = 0xcc447; + gp_coeff_2[28] = 0x5755d; + gp_coeff_2[29] = 0x5dd57; + gp_coeff_2[30] = 0x54747; + gp_coeff_2[31] = 0x5747c; + gp_coeff_2[32] = 0xc77dd; + gp_coeff_2[33] = 0x47557; + gp_coeff_2[34] = 0x7a22a; + gp_coeff_2[35] = 0xc73aa; + gp_coeff_2[36] = 0x77777; + gp_cv_g1 = 0x2b2834; + gp_cv_g2 = 0x3f6c2e; + } else if ((Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3)) { + gp_coeff_1[0] = 0x47777; + gp_coeff_1[1] = 0x77777; + gp_coeff_1[2] = 0x5d777; + gp_coeff_1[3] = 0x47777; + gp_coeff_1[4] = 0x75777; + gp_coeff_1[5] = 0x5c777; + gp_coeff_1[6] = 0x57777; + gp_coeff_1[7] = 0x44777; + gp_coeff_1[8] = 0x55d77; + gp_coeff_1[9] = 0x7d777; + gp_coeff_1[10] = 0x55577; + gp_coeff_1[11] = 0xd5d77; + gp_coeff_1[12] = 0xd7d77; + gp_coeff_1[13] = 0x47477; + gp_coeff_1[14] = 0xdc777; + gp_coeff_1[15] = 0x4cc77; + gp_coeff_1[16] = 0x77d57; + gp_coeff_1[17] = 0xc4777; + gp_coeff_1[18] = 0xdd7d7; + gp_coeff_1[19] = 0x7c757; + gp_coeff_1[20] = 0xd4477; + gp_coeff_1[21] = 0x755c7; + gp_coeff_1[22] = 0x47d57; + gp_coeff_1[23] = 0xd7c47; + gp_coeff_1[24] = 0xd4cc7; + gp_coeff_1[25] = 0x47577; + gp_coeff_1[26] = 0x5c7d5; + gp_coeff_1[27] = 0x4c75d; + gp_coeff_1[28] = 0xd57d7; + gp_coeff_1[29] = 0x44755; + gp_coeff_1[30] = 0x7557d; + gp_coeff_1[31] = 0xc477d; + gp_coeff_1[32] = 0xd5d44; + gp_coeff_1[33] = 0xdd77d; + gp_coeff_1[34] = 0x5d75b; + gp_coeff_1[35] = 0x74332; + gp_coeff_1[36] = 0xd4311; + gp_coeff_2[0] = 0xd7777; + gp_coeff_2[1] = 0x77777; + gp_coeff_2[2] = 0xdd777; + gp_coeff_2[3] = 0xdc777; + gp_coeff_2[4] = 0xc7777; + gp_coeff_2[5] = 0xdd777; + gp_coeff_2[6] = 0x77d77; + gp_coeff_2[7] = 0x77777; + gp_coeff_2[8] = 0x55777; + gp_coeff_2[9] = 0xc7d77; + gp_coeff_2[10] = 0xd4777; + gp_coeff_2[11] = 0xc7477; + gp_coeff_2[12] = 0x7c777; + gp_coeff_2[13] = 0xd5577; + gp_coeff_2[14] = 0xdd557; + gp_coeff_2[15] = 0x47577; + gp_coeff_2[16] = 0xd7477; + gp_coeff_2[17] = 0x55747; + gp_coeff_2[18] = 0xdd757; + gp_coeff_2[19] = 0xd7477; + gp_coeff_2[20] = 0x7d7d5; + gp_coeff_2[21] = 0xddd47; + gp_coeff_2[22] = 0xdd777; + gp_coeff_2[23] = 0x575d5; + gp_coeff_2[24] = 0x47547; + gp_coeff_2[25] = 0x555c7; + gp_coeff_2[26] = 0x7d447; + gp_coeff_2[27] = 0xd7447; + gp_coeff_2[28] = 0x757dd; + gp_coeff_2[29] = 0x7dc77; + gp_coeff_2[30] = 0x54747; + gp_coeff_2[31] = 0xc743b; + gp_coeff_2[32] = 0xd7c7c; + gp_coeff_2[33] = 0xd7557; + gp_coeff_2[34] = 0x55c7a; + gp_coeff_2[35] = 0x4cc29; + gp_coeff_2[36] = 0x77777; + gp_cv_g1 = 0x20682b; + gp_cv_g2 = 0x29322f; + } else if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I) { + gp_coeff_1[0] = 0x77777; + gp_coeff_1[1] = 0x75777; + gp_coeff_1[2] = 0x7d777; + gp_coeff_1[3] = 0xd7777; + gp_coeff_1[4] = 0x74777; + gp_coeff_1[5] = 0xcc777; + gp_coeff_1[6] = 0x57777; + gp_coeff_1[7] = 0x5d577; + gp_coeff_1[8] = 0x5dd77; + gp_coeff_1[9] = 0x74777; + gp_coeff_1[10] = 0x77577; + gp_coeff_1[11] = 0x77c77; + gp_coeff_1[12] = 0xdc477; + gp_coeff_1[13] = 0x5d577; + gp_coeff_1[14] = 0x575d7; + gp_coeff_1[15] = 0xc7d57; + gp_coeff_1[16] = 0x77777; + gp_coeff_1[17] = 0x557d7; + gp_coeff_1[18] = 0xc7557; + gp_coeff_1[19] = 0x75c77; + gp_coeff_1[20] = 0x477d7; + gp_coeff_1[21] = 0xcc747; + gp_coeff_1[22] = 0x47dd7; + gp_coeff_1[23] = 0x775d7; + gp_coeff_1[24] = 0x47447; + gp_coeff_1[25] = 0x75cc7; + gp_coeff_1[26] = 0xc7777; + gp_coeff_1[27] = 0xc75d5; + gp_coeff_1[28] = 0x44c7d; + gp_coeff_1[29] = 0x74c47; + gp_coeff_1[30] = 0x47d75; + gp_coeff_1[31] = 0x7d57c; + gp_coeff_1[32] = 0xd5dc4; + gp_coeff_1[33] = 0xdd575; + gp_coeff_1[34] = 0xdb3bb; + gp_coeff_1[35] = 0x5c752; + gp_coeff_1[36] = 0x90880; + gp_coeff_2[0] = 0x5d777; + gp_coeff_2[1] = 0xd7777; + gp_coeff_2[2] = 0x77777; + gp_coeff_2[3] = 0xd5d77; + gp_coeff_2[4] = 0xc7777; + gp_coeff_2[5] = 0xd7777; + gp_coeff_2[6] = 0xddd77; + gp_coeff_2[7] = 0x55777; + gp_coeff_2[8] = 0x57777; + gp_coeff_2[9] = 0x54c77; + gp_coeff_2[10] = 0x4c477; + gp_coeff_2[11] = 0x74777; + gp_coeff_2[12] = 0xd5d77; + gp_coeff_2[13] = 0x47757; + gp_coeff_2[14] = 0x75577; + gp_coeff_2[15] = 0xc7577; + gp_coeff_2[16] = 0x4c747; + gp_coeff_2[17] = 0x7d477; + gp_coeff_2[18] = 0x7c757; + gp_coeff_2[19] = 0x55dd5; + gp_coeff_2[20] = 0x57577; + gp_coeff_2[21] = 0x44c47; + gp_coeff_2[22] = 0x5cc75; + gp_coeff_2[23] = 0x4cc77; + gp_coeff_2[24] = 0x47547; + gp_coeff_2[25] = 0x777d5; + gp_coeff_2[26] = 0xcccc7; + gp_coeff_2[27] = 0x57447; + gp_coeff_2[28] = 0xdc757; + gp_coeff_2[29] = 0x5755c; + gp_coeff_2[30] = 0x44747; + gp_coeff_2[31] = 0x5d5dd; + gp_coeff_2[32] = 0x5747b; + gp_coeff_2[33] = 0x77557; + gp_coeff_2[34] = 0xdcb2a; + gp_coeff_2[35] = 0xd5779; + gp_coeff_2[36] = 0x77777; + gp_cv_g1 = 0x72242f; + gp_cv_g2 = 0x28822a; + } + + if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC) || + (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J)) { + sif_co_mx = 0xb8; + sif_fi_mx = 0x0; + sif_ic_bw = 0x1; + sif_bb_bw = 0x1; + sif_deemp = 0x1; + sif_cfg_demod = (sound_format == 0) ? 0x0:0x2; + sif_fm_gain = 0x4; + } else if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG) + || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG)) { + sif_co_mx = 0xa6; + sif_fi_mx = 0x10; + sif_ic_bw = 0x2; + sif_bb_bw = 0x0; + sif_deemp = 0x2; + sif_cfg_demod = (sound_format == 0) ? 0x0:0x2; + sif_fm_gain = 0x3; + } else if (Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK1) { + sif_co_mx = 154; + sif_fi_mx = 240; + sif_ic_bw = 2; + sif_bb_bw = 0; + sif_deemp = 2; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } else if (Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2) { + sif_co_mx = 150; + sif_fi_mx = 16; + sif_ic_bw = 2; + sif_bb_bw = 0; + sif_deemp = 2; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } else if (Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3) { + sif_co_mx = 158; + sif_fi_mx = 208; + sif_ic_bw = 3; + sif_bb_bw = 0; + sif_deemp = 2; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } else if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I) + || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I)) { + sif_co_mx = 153; + sif_fi_mx = 56; + sif_ic_bw = 3; + sif_bb_bw = 0; + sif_deemp = 2; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } else if (Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG_NICAM) { + sif_co_mx = 163; + sif_fi_mx = 40; + sif_ic_bw = 0; + sif_bb_bw = 0; + sif_deemp = 2; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } else if (Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { + sif_co_mx = 159; + sif_fi_mx = 200; + sif_ic_bw = 3; + sif_bb_bw = 0; + sif_deemp = 0; + sif_cfg_demod = (sound_format == 0) ? 1:2; + sif_fm_gain = 5; + } else if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) + || (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK)) { + sif_co_mx = 159; + sif_fi_mx = 200; + sif_ic_bw = 3; + sif_bb_bw = 0; + sif_deemp = 2; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } else if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) { + sif_co_mx = 182; + sif_fi_mx = 16; + sif_ic_bw = 1; + sif_bb_bw = 0; + sif_deemp = 1; + sif_cfg_demod = (sound_format == 0) ? 0:2; + sif_fm_gain = 3; + } + sif_fm_gain -= 2; /*avoid sound overflow@guanzhong*/ + /*FE PATH*/ + pr_info("ATV-DMD configure mixer\n"); + if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { + tmp_int = (Tuner_IF_Frequency/125000); + if (Tuner_Input_IF_inverted == 0x0) + mixer1 = -tmp_int; + else + mixer1 = tmp_int; + + mixer3 = 0; + mixer3_bypass = 0; + } else { + tmp_int = (Tuner_IF_Frequency/125000); + pr_info("ATV-DMD configure mixer 1\n"); + + if (Tuner_Input_IF_inverted == 0x0) + mixer1 = 0xe8 - tmp_int; + else + mixer1 = tmp_int - 0x18; + + pr_info("ATV-DMD configure mixer 2\n"); + mixer3 = 0x30; + mixer3_bypass = 0x1; + } + + pr_info("ATV-DMD configure mixer 3\n"); + atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, mixer1); + atv_dmd_wr_word(APB_BLOCK_ADDR_MIXER_3, 0x0, + (((mixer3 & 0xff) << 8) | (mixer3_bypass & 0xff))); + + if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) + atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03180e0f); + else + atv_dmd_wr_long(APB_BLOCK_ADDR_ADC_SE, 0x0, 0x03150e0f); + if (amlatvdemod_devp->tuner_id == AM_TUNER_R840) { + /*config pwm for tuner r840*/ + atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_SE, 1, 0xf); + } + + /*GP Filter*/ + pr_info("ATV-DMD configure GP_filter\n"); + if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { + cv = gp_cv_g1; + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x0, + (0x08000000 | (cv & 0x7fffff))); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x4, 0x04); + for (i = 0; i < 9; i = i + 1) { + /*super_coef = {gp_coeff_1[i*4],gp_coeff_1[i*4+1],*/ + /*gp_coeff_1[i*4+2],gp_coeff_1[i*4+3]};*/ + super_coef0 = + (((gp_coeff_1[i * 4 + 2] & 0xfff) << 20) | + (gp_coeff_1[i * 4 + 3] & 0xfffff)); + super_coef1 = + (((gp_coeff_1[i * 4] & 0xf) << 28) | + ((gp_coeff_1[i * 4 + 1] & 0xfffff) << 8) | + ((gp_coeff_1[i * 4 + 2] >> 12) & 0xff)); + super_coef2 = ((gp_coeff_1[i * 4] >> 4) & 0xffff); + + /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT,*/ + /*0x8,super_coef[79:48]);*/ + /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT,*/ + /*0xC,super_coef[47:16]);*/ + /*atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT,*/ + /*0x10,super_coef[15:0]);*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, + (((super_coef2 & 0xffff) << 16) | + ((super_coef1 & 0xffff0000) >> 16))); + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0xC, + (((super_coef1 & 0xffff) << 16) | + ((super_coef0 & 0xffff0000) >> 16))); + atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, 0x10, + (super_coef0 & 0xffff)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, i); + } + /*atv_dmd_wr_long*/ + /*(APB_BLOCK_ADDR_GP_VD_FLT,0x8,{gp_coeff_1[36],12'd0});*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, + ((gp_coeff_1[36] & 0xfffff) << 12)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, 0x09); + + } else { + cv = gp_cv_g1 - gp_cv_g2; + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x0, cv & 0x7fffff); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x4, 0x00); + for (i = 0; i < 9; i = i + 1) { + /*super_coef = {gp_coeff_1[i*4],gp_coeff_1[i*4+1],*/ + /*gp_coeff_1[i*4+2],gp_coeff_1[i*4+3]};*/ + super_coef0 = + (((gp_coeff_1[i * 4 + 2] & 0xfff) << 20) | + (gp_coeff_1[i * 4 + 3] & 0xfffff)); + super_coef1 = + (((gp_coeff_1[i * 4] & 0xf) << 28) | + ((gp_coeff_1[i * 4 + 1] & 0xfffff) << 8) | + ((gp_coeff_1[i * 4 + 2] >> 12) & 0xff)); + super_coef2 = ((gp_coeff_1[i * 4] >> 4) & 0xffff); + + /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT,*/ + /*0x8,super_coef[79:48]);*/ + /*atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT,*/ + /*0xC,super_coef[47:16]);*/ + /*atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT,*/ + /*0x10,super_coef[15:0]);*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, + (((super_coef2 & 0xffff) << 16) | + ((super_coef1 & 0xffff0000) >> 16))); + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0xC, + (((super_coef1 & 0xffff) << 16) | + ((super_coef0 & 0xffff0000) >> 16))); + atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, 0x10, + (super_coef0 & 0xffff)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, i); + + /* + * atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, + * 0x8,{gp_coeff_1[36],12'd0}); + */ + } + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, + ((gp_coeff_1[36] & 0xfffff) << 12)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, 9); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x4, 0x01); + + for (i = 0; i < 9; i = i + 1) { + /*super_coef = {gp_coeff_2[i*4],gp_coeff_2[i*4+1],*/ + /*gp_coeff_2[i*4+2],gp_coeff_2[i*4+3]};*/ + super_coef0 = + (((gp_coeff_2[i * 4 + 2] & 0xfff) << 20) | + (gp_coeff_2[i * 4 + 3] & 0xfffff)); + super_coef1 = + (((gp_coeff_2[i * 4] & 0xf) << 28) | + ((gp_coeff_2[i * 4 + 1] & 0xfffff) << 8) | + ((gp_coeff_2[i * 4 + 2] >> 12) & 0xff)); + super_coef2 = ((gp_coeff_2[i * 4] >> 4) & 0xffff); + + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, + (((super_coef2 & 0xffff) << 16) | + ((super_coef1 & 0xffff0000) >> 16))); + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0xC, + (((super_coef1 & 0xffff) << 16) | + ((super_coef0 & 0xffff0000) >> 16))); + atv_dmd_wr_word(APB_BLOCK_ADDR_GP_VD_FLT, 0x10, + (super_coef0 & 0xffff)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, i); + } + + atv_dmd_wr_long(APB_BLOCK_ADDR_GP_VD_FLT, 0x8, + ((gp_coeff_2[36] & 0xfffff) << 12)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GP_VD_FLT, 0x05, 0x09); + } + + /*CRVY*/ + pr_info("ATV-DMD configure CRVY\n"); + if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { + crvy_reg_1 = 0xFF; + crvy_reg_2 = 0x00; + } else { + crvy_reg_1 = 0x04; + crvy_reg_2 = 0x01; + } + + atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x29, crvy_reg_1); + pr_info("ATV-DMD configure rcvy 2\n"); + pr_info("ATV-DMD configure rcvy, crvy_reg_2 = %x\n", crvy_reg_2); + atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x20, crvy_reg_2); + + /*SOUND SUPPRESS*/ + pr_info("ATV-DMD configure sound suppress\n"); + + if ((Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) || + (sound_format == 0)) + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_VD_IF, 0x02, 0x01); + else + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_VD_IF, 0x02, 0x00); + + /*SIF*/ + pr_info("ATV-DMD configure sif\n"); + if (!(Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV)) { + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x03, sif_ic_bw); + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x01, sif_fi_mx); + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_IC_STD, 0x02, sif_co_mx); + + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x00, + (((sif_bb_bw & 0xff) << 24) | + ((sif_deemp & 0xff) << 16) | 0x0500 | + sif_fm_gain)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x06, sif_cfg_demod); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x24, + (((sif_bb_bw & 0xff) << 24) | + 0xfffff)); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0x1c, 0x1f000); + } + + if (Broadcast_Standard != AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { + if (sound_format == 0) { + tmp_int = 0; + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_3, 0x00, + (0x01000000 | (tmp_int & 0xffffff))); + } else { + tmp_int = (256 - sif_co_mx) << 13; + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_3, 0x00, + (tmp_int & 0xffffff)); + } + } + + if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { + atv_dmd_wr_long(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x02040E0A); + atv_dmd_wr_word(APB_BLOCK_ADDR_IC_AGC, 0x04, 0x0F0D); + } else if (sound_format == 0) + atv_dmd_wr_byte(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x04); + else if (Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { + atv_dmd_wr_long(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x0003140A); + atv_dmd_wr_word(APB_BLOCK_ADDR_IC_AGC, 0x04, 0x1244); + } else { + atv_dmd_wr_long(APB_BLOCK_ADDR_IC_AGC, 0x00, 0x00040E0A); + atv_dmd_wr_word(APB_BLOCK_ADDR_IC_AGC, 0x04, 0x0D68); + } + + /*VAGC*/ + pr_info("ATV-DMD configure vagc\n"); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x48, 0x9B6F2C00); + /*bw select mode*/ + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x37, 0x1C); + /*disable prefilter*/ + + if (Broadcast_Standard == AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L) { + atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x44, 0x4450); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x46, 0x44); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x4, 0x3E04FC); + atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x3C, 0x4848); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x3E, 0x48); + } else { + atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x44, 0xB800); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x46, 0x08); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x4, 0x3C04FC); + atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x3C, 0x1818); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x3E, 0x10); + } + + /*tmp_real = $itor(Hz_Freq)/0.23841858; //TODO*/ + /*tmp_int = $rtoi(tmp_real); //TODO*/ + /*tmp_int = Hz_Freq/0.23841858; //TODO*/ + /*tmp_int_2 = ((unsigned long)15625)*10000/23841858;*/ + /*tmp_int_2 = ((unsigned long)Hz_Freq)*10000/23841858;*/ + atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x10, + (freq_hz_cvrt >> 8) & 0xffff); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x12, (freq_hz_cvrt & 0xff)); + + /*OUTPUT STAGE*/ + pr_info("ATV-DMD configure output stage\n"); + if (Broadcast_Standard != AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV) { + atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x0, 0x00); + atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x1, 0x40); + atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x2, 0x40); + atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x4, 0xFA); + atv_dmd_wr_byte(APB_BLOCK_ADDR_DAC_UPS, 0x5, 0xFA); + } + + /*GDE FILTER*/ + pr_info("ATV-DMD configure gde filter\n"); + if (GDE_Curve == 0) { + gd_coeff[0] = 0x020; /*12'sd32;*/ + gd_coeff[1] = 0xf5f; /*-12'sd161;*/ + gd_coeff[2] = 0x1fe; /*12'sd510;*/ + gd_coeff[3] = 0xc0b; /*-12'sd1013;*/ + gd_coeff[4] = 0x536; /*12'sd1334;*/ + gd_coeff[5] = 0xb34; /*-12'sd1228;*/ + gd_bypass = 0x1; + } else if (GDE_Curve == 1) { + gd_coeff[0] = 0x8; /*12'sd8;*/ + gd_coeff[1] = 0xfd5; /*-12'sd43;*/ + gd_coeff[2] = 0x8d; /*12'sd141;*/ + gd_coeff[3] = 0xe69; /*-12'sd407;*/ + gd_coeff[4] = 0x1f1; /*12'sd497;*/ + gd_coeff[5] = 0xe7e; /*-12'sd386;*/ + gd_bypass = 0x1; + } else if (GDE_Curve == 2) { + gd_coeff[0] = 0x35; /*12'sd53;*/ + gd_coeff[1] = 0xf41; /*-12'sd191;*/ + gd_coeff[2] = 0x68; /*12'sd104;*/ + gd_coeff[3] = 0xea5; /*-12'sd347;*/ + gd_coeff[4] = 0x322; /*12'sd802;*/ + gd_coeff[5] = 0x1bb; /*12'sd443;*/ + gd_bypass = 0x1; + } else if (GDE_Curve == 3) { + gd_coeff[0] = 0xf; /*12'sd15;*/ + gd_coeff[1] = 0xfb5; /*-12'sd75;*/ + gd_coeff[2] = 0xcc; /*12'sd204;*/ + gd_coeff[3] = 0xe51; + gd_coeff[4] = 0x226; /*12'sd550;*/ + gd_coeff[5] = 0xd02; + gd_bypass = 0x1; + } else + gd_bypass = 0x0; + + if (gd_bypass == 0x0) + atv_dmd_wr_byte(APB_BLOCK_ADDR_GDE_EQUAL, 0x0D, gd_bypass); + else { + for (i = 0; i < 6; i = i + 1) + atv_dmd_wr_word(APB_BLOCK_ADDR_GDE_EQUAL, i << 1, + gd_coeff[i]); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GDE_EQUAL, 0x0C, 0x01); + atv_dmd_wr_byte(APB_BLOCK_ADDR_GDE_EQUAL, 0x0D, gd_bypass); + } + + /*PWM*/ + pr_info("ATV-DMD configure pwm\n"); + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x00, 0x1f40); /*4KHz*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x04, 0xc8); + /*26 dB dynamic range*/ + atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x09, 0xa); + if (amlatvdemod_devp->tuner_id == AM_TUNER_R840) { + /*config pwm for tuner r840*/ + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0, 0xc80); + /* guanzhong for Tuner AGC shock */ + atv_dmd_wr_long(APB_BLOCK_ADDR_AGC_PWM, 0x08, 0x46180200); + /* atv_dmd_wr_byte(APB_BLOCK_ADDR_ADC_SE,1,0xf);//Kd = 0xf */ + } +} + +void retrieve_adc_power(int *adc_level) +{ + *adc_level = atv_dmd_rd_long(APB_BLOCK_ADDR_ADC_SE, 0x0c); + /*adc_level = adc_level/32768*100;*/ + *adc_level = (*adc_level) * 100 / 32768; +} + +void retrieve_vpll_carrier_lock(int *lock) +{ + unsigned int data; + + data = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x43); + *lock = (data & 0x1); +} + +void retrieve_vpll_carrier_line_lock(int *lock) +{ + unsigned long data = 0; + int line_lock = 0; + int line_lock_strong = 0; + + data = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); + line_lock = data & 0x10; + line_lock_strong = data & 0x8; + + pr_info("line_lock = 0x%x, line_lock_strong = 0x%x\n", + line_lock, line_lock_strong); + + *lock = (line_lock | line_lock_strong); +} + +void retrieve_vpll_carrier_audio_power(int *power) +{ + unsigned long data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + + if (!(data & 0x80)) { + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, data | 0x80); + + usleep_range(10000, 10000 + 100); + + data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x03); + *power = data & 0xffff; + + data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, data & (~0x80)); + } else { + data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x03); + *power = data & 0xffff; + } + + pr_info("retrieve_vpll_carrier_audio_power: %d.\n", *power); +} + +int retrieve_vpll_carrier_afc(void) +{ + int data_ret, pll_lock, field_lock, line_lock, line_lock_strong; + unsigned long vd_lock = 0; + + pll_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x43)&0x1; + vd_lock = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); + field_lock = vd_lock & 0x4; + line_lock = vd_lock & 0x10; + line_lock_strong = vd_lock & 0x8; + + if ((pll_lock == 1) || (line_lock == 0x10)) { + /*if pll unlock, afc is invalid*/ + pr_err("[afc invalid] pll: %d, line: %d, line_strong: %d, field: %d.\n", + pll_lock, line_lock, + line_lock_strong, field_lock); + + data_ret = 0xffff;/* 500; */ + return data_ret; + } + + retrieve_frequency_offset(&data_ret); + + if ((abs(data_ret) < 50) && (line_lock_strong == 0x8) && + (field_lock == 0x4)) { + data_ret = 100; + return data_ret; + } + + return data_ret; +} + +void set_pll_lpf(unsigned int lock) +{ + atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x24, lock); +} + +void retrieve_frequency_offset(int *freq_offset) +{ + unsigned int data_h, data_l, data_exg; + int data_ret; + + data_h = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x40); + data_l = atv_dmd_rd_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x41); + data_exg = ((data_h & 0x7) << 8) | data_l; + if (data_h & 0x8) { + data_ret = (((~data_exg) & 0x7ff) - 1); + *freq_offset = data_ret * 488 * (-1) / 1000; + } else { + data_ret = data_exg * 488 / 1000; + *freq_offset = data_ret; + } +} +//EXPORT_SYMBOL(retrieve_frequency_offset); + +void retrieve_video_lock(int *lock) +{ + unsigned int data, wlock, slock; + + data = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); + wlock = data & 0x10; + slock = data & 0x8; + *lock = wlock & slock; +} + +void retrieve_field_lock(int *lock) +{ + unsigned int data, field_lock, line_lock; + + data = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f); + line_lock = data & 0x10; + field_lock = data & 0x4; + *lock = ((field_lock == 0) && (line_lock == 0)); +} + +void retrieve_fh_frequency(int *fh) +{ + unsigned long data1, data2; + + data1 = atv_dmd_rd_word(APB_BLOCK_ADDR_VDAGC, 0x58); + data2 = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x10); + data1 = data1 >> 11; + data2 = data2 >> 3; + *fh = data1 + data2; +} +/*tune mix to adapt afc*/ +void atvdemod_afc_tune(void) +{ + /* int adc_level,lock,freq_offset,fh; */ + int freq_offset, lock, mix1_freq_cur, delta_mix1_freq; + + /* retrieve_adc_power(&adc_level); */ + /* pr_info("adc_level: 0x%x\n",adc_level); */ + retrieve_vpll_carrier_lock(&lock); + mix1_freq_cur = atv_dmd_rd_byte(APB_BLOCK_ADDR_MIXER_1, 0x0); + delta_mix1_freq = abs(mix1_freq_cur - mix1_freq); + if ((lock&0x1) == 0) + pr_info("%s visual carrier lock:locked\n", __func__); + else + pr_info("%s visual carrier lock:unlocked\n", __func__); + /* set_pll_lpf(lock); */ + retrieve_frequency_offset(&freq_offset); + /* pr_info("visual carrier offset:%d Hz\n",*/ + /* freq_offset*48828125/100000); */ + /* retrieve_video_lock(&lock); */ + if ((lock&0x1) == 1) { + if (delta_mix1_freq == atvdemod_afc_range) + atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, mix1_freq); + else if ((freq_offset >= atvdemod_afc_offset) && + (delta_mix1_freq < atvdemod_afc_range)) + atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, + mix1_freq_cur-1); + else if ((freq_offset <= (-1)*atvdemod_afc_offset) && + (delta_mix1_freq < atvdemod_afc_range-1)) + atv_dmd_wr_byte(APB_BLOCK_ADDR_MIXER_1, 0x0, + mix1_freq_cur+1); + /* pr_info("video lock:locked\n"); */ + } + /* retrieve_fh_frequency(&fh); */ + /* pr_info("horizontal frequency:%d Hz\n",fh*190735/100000); */ +} + +static enum amlatvdemod_snr_level_e aml_atvdemod_get_snr_level(void) +{ + unsigned int snr_val, i, snr_d[8]; + enum amlatvdemod_snr_level_e ret; + unsigned long fsnr; + + snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; + fsnr = snr_val; + for (i = 1; i < 8; i++) { + snr_d[i] = snr_d[i-1]; + fsnr = fsnr + snr_d[i]; + } + snr_d[0] = snr_val; + fsnr = fsnr >> 3; + if (fsnr < 316) + ret = high; + else if (fsnr < 31600) + ret = ok_plus; + else if (fsnr < 158000) + ret = ok_minus; + else if (fsnr < 700000) + ret = low; + else + ret = very_low; + return ret; +} + +void atvdemod_monitor_serice(void) +{ + enum amlatvdemod_snr_level_e snr_level; + unsigned int vagc_bw_typ, vagc_bw_fast, vpll_kptrack, vpll_kitrack; + unsigned int agc_register, vfmat_reg, agc_pll_kptrack, agc_pll_kitrack; + /*1.get current snr*/ + snr_level = aml_atvdemod_get_snr_level(); + /*2.*/ + if (snr_level > very_low) { + vagc_bw_typ = 0x1818; + vagc_bw_fast = (snr_level == low) ? 0x18:0x10; + vpll_kptrack = 0x05; + vpll_kitrack = 0x0c; + agc_pll_kptrack = 0x6; + agc_pll_kitrack = 0xc; + } else { + vagc_bw_typ = 0x6f6f; + vagc_bw_fast = 0x6f; + vpll_kptrack = 0x06; + vpll_kitrack = 0x0e; + agc_pll_kptrack = 0x8; + agc_pll_kitrack = 0xf; + } + atv_dmd_wr_word(APB_BLOCK_ADDR_VDAGC, 0x3c, vagc_bw_typ); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x3e, vagc_bw_fast); + atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x23, vpll_kptrack); + atv_dmd_wr_byte(APB_BLOCK_ADDR_CARR_RCVY, 0x24, vpll_kitrack); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x0c, + ((atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x0c) & 0xf0)| + agc_pll_kptrack)); + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x0d, + ((atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x0d) & 0xf0)| + agc_pll_kitrack)); + /*3.*/ + agc_register = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x28); + if (snr_level < low) { + agc_register = ((agc_register&0xff80fe03) | (25 << 16) | + (15 << 2)); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x28, agc_register); + } else if (snr_level > low) { + agc_register = ((agc_register&0xff80fe03) | (38 << 16) | + (30 << 2)); + atv_dmd_wr_long(APB_BLOCK_ADDR_VDAGC, 0x28, agc_register); + } + /*4.*/ + if (snr_level < ok_minus) + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x47, + (atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x47) & 0x7f)); + else + atv_dmd_wr_byte(APB_BLOCK_ADDR_VDAGC, 0x47, + (atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x47) | 0x80)); + /*5.vformat*/ + if (snr_level < ok_minus) { + if (atv_dmd_rd_byte(APB_BLOCK_ADDR_VFORMAT, 0xe) != 0xf) + atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, 0xf); + } else if (snr_level > ok_minus) { + vfmat_reg = atv_dmd_rd_word(APB_BLOCK_ADDR_VFORMAT, 0x16); + if ((vfmat_reg << 4) < 0xf000) { + if (atv_dmd_rd_byte(APB_BLOCK_ADDR_VFORMAT, 0xe) == + 0x0f) + atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, + 0x6); + else + atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, + 0x6); + } + } else { + if (atv_dmd_rd_byte(APB_BLOCK_ADDR_VFORMAT, 0xe) == 0x0f) + atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, 0xe); + else + atv_dmd_wr_byte(APB_BLOCK_ADDR_VFORMAT, 0xe, 0xe); + } +} + +static int atvdemod_get_snr(struct dvb_frontend *fe) +{ + unsigned int snr_val = 0; + int ret = 0; + + snr_val = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC, 0x50) >> 8; + /* snr_val:900000~0xffffff,ret:5~15 */ + if (snr_val > 900000) + ret = 15 - (snr_val - 900000)*10/(0xffffff - 900000); + /* snr_val:158000~900000,ret:15~30 */ + else if (snr_val > 158000) + ret = 30 - (snr_val - 158000)*15/(900000 - 158000); + /* snr_val:31600~158000,ret:30~50 */ + else if (snr_val > 31600) + ret = 50 - (snr_val - 31600)*20/(158000 - 31600); + /* snr_val:316~31600,ret:50~80 */ + else if (snr_val > 316) + ret = 80 - (snr_val - 316)*30/(31600 - 316); + /* snr_val:0~316,ret:80~100 */ + else + ret = 100 - (316 - snr_val)*20/316; + return ret; +} + +void atvdemod_det_snr_serice(void) +{ + snr_val = atvdemod_get_snr(NULL); +} + +void atvdemod_timer_handler(unsigned long arg) +{ + if (atvdemod_timer_en == 0) + return; + + if (vdac_enable_check_dtv()) + return; + + atvdemod_timer.expires = jiffies + ATVDEMOD_INTERVAL*10;/*100ms timer*/ + add_timer(&atvdemod_timer); + if (atvdemod_afc_en) + atvdemod_afc_tune(); + if (atvdemod_monitor_en) + atvdemod_monitor_serice(); + if (audio_det_en) + aml_atvdemod_overmodule_det(); + if (atvdemod_det_snr_en) + atvdemod_det_snr_serice(); + if (audio_thd_en) + audio_thd_det(); + if (aml_atvdemod_get_btsc_sap_mode() == 1 && + aud_std == AUDIO_STANDARD_BTSC) + audio_mode_det(aud_mode); +} + +int atvdemod_clk_init(void) +{ + /* clocks_set_hdtv (); */ + /* 1.set system clock */ +#if 0 /* now set pll in tvafe_general.c */ + if (is_meson_txl_cpu()) { + amlatvdemod_hiu_reg_write(HHI_VDAC_CNTL0, 0x6e0201); + amlatvdemod_hiu_reg_write(HHI_VDAC_CNTL1, 0x8); + /* for TXL(T962) */ + pr_err("%s in TXL\n", __func__); + + /* W_HIU_REG(HHI_ADC_PLL_CNTL, 0x30c54260); */ + #if 0 + W_HIU_REG(HHI_ADC_PLL_CNTL, 0x30f14250); + W_HIU_REG(HHI_ADC_PLL_CNTL1, 0x22000442); + W_HIU_REG(HHI_ADC_PLL_CNTL2, 0x5ba00380); + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xac6a2114); + W_HIU_REG(HHI_ADC_PLL_CNTL4, 0x02953004); + W_HIU_REG(HHI_ADC_PLL_CNTL5, 0x00030a00); + W_HIU_REG(HHI_ADC_PLL_CNTL6, 0x00005000); + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x2c6a2114); + #else /* get from feijun 2015/07/19 */ + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); + W_HIU_REG(HHI_ADC_PLL_CNTL, 0x30f14250); + W_HIU_REG(HHI_ADC_PLL_CNTL1, 0x22000442); + /*0x5ba00380 from pll;0x5ba00384 clk form crystal*/ + W_HIU_REG(HHI_ADC_PLL_CNTL2, 0x5ba00384); + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); + W_HIU_REG(HHI_ADC_PLL_CNTL4, 0x02913004); + W_HIU_REG(HHI_ADC_PLL_CNTL5, 0x00034a00); + W_HIU_REG(HHI_ADC_PLL_CNTL6, 0x00005000); + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xca6a2110); + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a6a2110); + #endif + W_HIU_REG(HHI_DADC_CNTL, 0x00102038); + W_HIU_REG(HHI_DADC_CNTL2, 0x00000406); + W_HIU_REG(HHI_DADC_CNTL3, 0x00082183); + + } else { + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0xca2a2110); + W_HIU_REG(HHI_ADC_PLL_CNTL4, 0x2933800); + W_HIU_REG(HHI_ADC_PLL_CNTL, 0xe0644220); + W_HIU_REG(HHI_ADC_PLL_CNTL2, 0x34e0bf84); + W_HIU_REG(HHI_ADC_PLL_CNTL3, 0x4a2a2110); + + W_HIU_REG(HHI_ATV_DMD_SYS_CLK_CNTL, 0x80); + /* TVFE reset */ + W_HIU_BIT(RESET1_REGISTER, 1, 7, 1); + } +#endif + W_HIU_REG(HHI_ATV_DMD_SYS_CLK_CNTL, 0x80); + + /* read_version_register(); */ + + /*2.set atv demod top page control register*/ + atv_dmd_input_clk_32m(); + atv_dmd_wr_long(APB_BLOCK_ADDR_TOP, ATV_DMD_TOP_CTRL, 0x1037); + atv_dmd_wr_long(APB_BLOCK_ADDR_TOP, (ATV_DMD_TOP_CTRL1 << 2), 0x1f); + + /*3.configure atv demod*/ + check_communication_interface(); + power_on_receiver(); + pr_err("%s done\n", __func__); + + return 0; +} + +int amlfmt_aud_standard(int broad_std) +{ + int std = 0; + int nicam_lock = 0; + uint32_t reg_value = 0; + + switch (broad_std) { + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: + std = AUDIO_STANDARD_BTSC; + configure_adec(std); + adec_soft_reset(); + msleep(audio_a2_delay); + + /* maybe need wait */ + reg_value = adec_rd_reg(CARRIER_MAG_REPORT); + pr_info("\n%s 0x%x\n", __func__, (reg_value>>16)&0xffff); + if (((reg_value>>16)&0xffff) > audio_a2_threshold) + std = AUDIO_STANDARD_A2_K; + else + std = AUDIO_STANDARD_BTSC; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J: + std = AUDIO_STANDARD_EIAJ; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + std = AUDIO_STANDARD_NICAM_BG; + configure_adec(std); + adec_soft_reset(); + mdelay(2); + /* need wait */ + reg_value = adec_rd_reg(0x1a3); + nicam_lock = (reg_value>>28)&1; + + if (nicam_lock) + std = AUDIO_STANDARD_NICAM_BG; + else + std = AUDIO_STANDARD_A2_BG; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + std = AUDIO_STANDARD_NICAM_DK; + configure_adec(aud_std); + adec_soft_reset(); + mdelay(2); + /* need wait */ + reg_value = adec_rd_reg(0x1a3); + nicam_lock = (reg_value>>28)&1; + if (nicam_lock) + std = AUDIO_STANDARD_NICAM_DK; + else + std = AUDIO_STANDARD_A2_DK2; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + std = AUDIO_STANDARD_NICAM_I; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: + std = AUDIO_STANDARD_NICAM_L; + break; + } + pr_err("%s detect aud std:%d\n", __func__, std); + return std; +} + +int atvauddemod_init(void) +{ + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + if (aud_auto) + aud_std = amlfmt_aud_standard(broad_std); + configure_adec(aud_std); + adec_soft_reset(); + set_outputmode(aud_std, aud_mode); + } + return 0; +} + +void atvauddemod_set_outputmode(void) +{ + set_outputmode(aud_std, aud_mode); +} + +int atvdemod_init(void) +{ + /* unsigned long data32; */ + if (atvdemod_timer_en == 1) { + if (timer_init_flag == 1) { + del_timer_sync(&atvdemod_timer); + timer_init_flag = 0; + } + } + + /* 1.set system clock when atv enter*/ + + pr_err("%s do configure_receiver ...\n", __func__); + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) + sound_format = 1; + configure_receiver(broad_std, if_freq, if_inv, gde_curve, sound_format); + pr_err("%s do atv_dmd_misc ...\n", __func__); + atv_dmd_misc(); + + pr_err("%s do atv_dmd_soft_reset ...\n", __func__); + /*4.software reset*/ + atv_dmd_soft_reset(); + atv_dmd_soft_reset(); + atv_dmd_soft_reset(); + atv_dmd_soft_reset(); + + /* ????? + * while (!all_lock) { + * data32 = atv_dmd_rd_long(APB_BLOCK_ADDR_VDAGC,0x13<<2); + * if ((data32 & 0x1c) == 0x0) { + * all_lock = 1; + * } + * delay_us(400); + * } + */ + #if 1/* temp mark */ + if (atvdemod_timer_en == 1) { + if (audio_thd_en) + audio_thd_init(); + /*atvdemod timer handler*/ + init_timer(&atvdemod_timer); + /* atvdemod_timer.data = (ulong) devp; */ + atvdemod_timer.function = atvdemod_timer_handler; + /* after 3s enable demod auto detect */ + atvdemod_timer.expires = jiffies + ATVDEMOD_INTERVAL*300; + add_timer(&atvdemod_timer); + mix1_freq = atv_dmd_rd_byte(APB_BLOCK_ADDR_MIXER_1, 0x0); + timer_init_flag = 1; + } + #endif + pr_err("%s done\n", __func__); + return 0; +} +void atvdemod_uninit(void) +{ + /* del the timer */ + if (atvdemod_timer_en == 1) { + if (timer_init_flag == 1) { + del_timer_sync(&atvdemod_timer); + timer_init_flag = 0; + } + } +} + +void atv_dmd_set_std(void) +{ + v4l2_std_id ptstd = amlatvdemod_devp->std; + /* set broad standard of tuner*/ + if ((ptstd & V4L2_STD_B) || (ptstd & V4L2_STD_G)) { + /* V4L2_STD_PAL_B | V4L2_STD_PAL_B1 | V4L2_STD_SECAM_B + * | V4L2_STD_PAL_G | V4L2_STD_SECAM_G + */ + amlatvdemod_devp->fre_offset = 2250000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; + if_freq = 3250000; + gde_curve = 2; + } else if (ptstd & V4L2_STD_DK) { + /* V4L2_STD_PAL_D | V4L2_STD_PAL_K | + * V4L2_STD_SECAM_D | V4L2_STD_SECAM_K + */ + amlatvdemod_devp->fre_offset = 2250000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; + if_freq = 3250000; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; + gde_curve = 3; + } else if (ptstd & V4L2_STD_PAL_M) { + /* V4L2_STD_PAL_M */ + amlatvdemod_devp->fre_offset = 2250000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + if_freq = 4250000; + gde_curve = 0; + } else if (ptstd & V4L2_STD_NTSC_M) { + /* V4L2_STD_NTSC_M */ + amlatvdemod_devp->fre_offset = 1750000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_60HZ_VERT; + if_freq = 4250000; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC; + gde_curve = 0; + } else if (ptstd & V4L2_STD_NTSC_M_JP) { + /* V4L2_STD_NTSC_M_JP */ + amlatvdemod_devp->fre_offset = 1750000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J; + if_freq = 4250000; + gde_curve = 0; + } else if (ptstd & V4L2_STD_PAL_I) { + /* V4L2_STD_PAL_I */ + amlatvdemod_devp->fre_offset = 2750000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; + if_freq = 3250000; + gde_curve = 4; + } else if (ptstd & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC)) { + /* V4L2_STD_SECAM_L | V4L2_STD_SECAM_LC */ + amlatvdemod_devp->fre_offset = 2750000; + freq_hz_cvrt = AML_ATV_DEMOD_FREQ_50HZ_VERT; + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L; + gde_curve = 4; + } + + if (amlatvdemod_devp->tuner_id == AM_TUNER_R840) { + if_freq = amlatvdemod_devp->if_freq; + if_inv = amlatvdemod_devp->if_inv; + } else if (amlatvdemod_devp->tuner_id == AM_TUNER_MXL661) { + if_freq = amlatvdemod_devp->if_freq; + if_inv = amlatvdemod_devp->if_inv; + } else if (amlatvdemod_devp->tuner_id == AM_TUNER_SI2151) { + if_freq = amlatvdemod_devp->if_freq; + if_inv = amlatvdemod_devp->if_inv; + } + + pr_info("[atvdemod]%s:broad_std %d,freq_hz_cvrt:0x%x,fre_offset:%d.\n", + __func__, broad_std, freq_hz_cvrt, + amlatvdemod_devp->fre_offset); + if (atvdemod_init()) + pr_info("[atvdemod..]%s: atv restart error.\n", __func__); +} + +int aml_audiomode_autodet(struct dvb_frontend *fe) +{ + struct atv_demod_priv *priv = fe->analog_demod_priv; + struct aml_atvdemod_parameters *param = &priv->atvdemod_param; + + unsigned long carrier_power = 0; + unsigned long carrier_power_max = 0; + unsigned long carrier_power_average_max = 0; + unsigned long carrier_power_average[4] = {0}; + unsigned long reg_addr = 0x03, temp_data; + int carrier_lock_count = 0; + int lock = 0; + int broad_std_final = 0; + int num = 0, i = 0, final_id = 0; + int delay_ms = 10, delay_ms_default = 10; + int cur_std = ID_PAL_DK; + +#if 0 + temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data | 0x80;/* 0x40 */ + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); +#endif + + switch (broad_std) { + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC: + + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M; + atvdemod_init(); + temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data & (~0x80); /* 0xbf; */ + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ + return broad_std; + + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2: + case AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3: + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L; + atvdemod_init(); + temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + + temp_data = temp_data & (~0x80); /* 0xbf; */ + + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + /* pr_err("%s, SECAM ,audio set SECAM_L\n", __func__); */ + return broad_std; + default: + pr_err("unsupport broadcast_standard!!!\n"); + temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data & (~0x80); /* 0xbf; */ + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + return broad_std; + } + /* ----------------read carrier_power--------------------- */ + /* SIF_STG_2[0x09],address 0x03 */ + while (1) { + if (num >= 4) { + temp_data = + atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data & (~0x80); + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, + temp_data); + carrier_power_max = carrier_power_average[0]; + for (i = 0; i < ID_MAX; i++) { + if (carrier_power_max + < carrier_power_average[i]) { + carrier_power_max = + carrier_power_average[i]; + final_id = i; + } + } + switch (final_id) { + case ID_PAL_I: + broad_std_final = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; + break; + case ID_PAL_BG: + broad_std_final = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; + break; + case ID_PAL_M: + broad_std_final = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + break; + case ID_PAL_DK: + broad_std_final = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; + break; + } + carrier_power_average_max = carrier_power_max; + broad_std = broad_std_final; + pr_err("%s:broad_std:%d,carrier_power_average_max:%lu\n", + __func__, broad_std, carrier_power_average_max); + if (carrier_power_average_max < 150) + pr_err("%s,carrier too low error\n", __func__); + if (broad_std == AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M) { + /*the max except palm*/ + carrier_power_average[final_id] = 0; + final_id = 0; + carrier_power_max = carrier_power_average[0]; + for (i = 0; i < ID_MAX; i++) { + if (carrier_power_max + < carrier_power_average[i]) { + carrier_power_max = + carrier_power_average[i]; + final_id = i; + } + } + switch (final_id) { + case ID_PAL_I: + broad_std_except_pal_m = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; + break; + case ID_PAL_BG: + broad_std_except_pal_m = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; + break; + case ID_PAL_DK: + broad_std_except_pal_m = + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; + break; + } + } + if (priv != NULL) { + param->param.std = V4L2_STD_PAL; + switch (broad_std) { + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + param->param.std |= V4L2_STD_PAL_DK; + param->param.audmode = V4L2_STD_PAL_DK; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + param->param.std |= V4L2_STD_PAL_I; + param->param.audmode = V4L2_STD_PAL_I; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + param->param.std |= V4L2_STD_PAL_BG; + param->param.audmode = V4L2_STD_PAL_BG; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: + param->param.std |= V4L2_STD_PAL_M; + param->param.audmode = V4L2_STD_PAL_M; + break; + default: + param->param.std |= V4L2_STD_PAL_DK; + param->param.audmode = V4L2_STD_PAL_DK; + } + param->param.frequency += 1; + fe->ops.analog_ops.set_params(fe, + ¶m->param); + } + return broad_std; + } + switch (broad_std) { + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK: + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I; + cur_std = ID_PAL_I; + if (priv != NULL) { + param->param.std = V4L2_STD_PAL_I; + param->param.frequency += 1; + param->param.audmode = V4L2_STD_PAL_I; + } + delay_ms = delay_ms_default; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I: + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG; + cur_std = ID_PAL_BG; + if (priv != NULL) { + param->param.std = V4L2_STD_PAL_BG; + param->param.frequency += 1; + param->param.audmode = V4L2_STD_PAL_BG; + } + delay_ms = delay_ms_default; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG: + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M; + cur_std = ID_PAL_M; + if (priv != NULL) { + param->param.std = V4L2_STD_PAL_M; + param->param.frequency += 1; + param->param.audmode = V4L2_STD_PAL_M; + } + delay_ms = delay_ms_default; + break; + case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M: + broad_std = AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK; + cur_std = ID_PAL_DK; + if (priv != NULL) { + param->param.std = V4L2_STD_PAL_DK; + param->param.frequency += 1; + param->param.audmode = V4L2_STD_PAL_DK; + } + delay_ms = delay_ms_default; + break; + + default: + pr_err("unsupport broadcast_standard!!!\n"); + break; + } + if (priv != NULL) + fe->ops.analog_ops.set_params(fe, ¶m->param); + /* atvdemod_init(); //set_frontend has already been called it */ + + /* enable audio detect function */ + temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data | 0x80;/* 0x40 */ + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + + usleep_range(delay_ms*1000, delay_ms*1000+100); + + carrier_lock_count = 0; + i = 4; + while (i--) { + retrieve_vpll_carrier_lock(&lock); + if (lock == 0) + break; + carrier_lock_count++; + if (carrier_lock_count >= 20) { + pr_err("%s step2, retrieve_vpll_carrier_lock failed\n", + __func__); + /* return broad_std; */ + } + usleep_range(6000, 9000); + } + /* ----------------read carrier_power--------------------- */ + for (i = 0; i < 100; i++) { + carrier_power = + atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, + reg_addr); + carrier_power_max += carrier_power; + } + carrier_power = carrier_power_max/i; + carrier_power_max = 0; + pr_err("[amlatvdemod.. %d,std:%d ]%s: atvdemo audio carrier power report:%lu. @@@@@@@@@@\n", + num, broad_std, __func__, carrier_power); + carrier_power_average[cur_std] += carrier_power; + num++; + } + + return broad_std; +} + +void aml_audio_valume_gain_set(unsigned int audio_gain) +{ + unsigned long audio_gain_data, temp_data; + + if (audio_gain > 0xfff) { + pr_err("Error: atv in gain max 7.998, min 0.002! gain = value/512\n"); + pr_err("value (0~0xfff)\n"); + return; + } + audio_gain_data = audio_gain & 0xfff; + temp_data = atv_dmd_rd_word(APB_BLOCK_ADDR_MONO_PROC, 0x52); + temp_data = (temp_data & 0xf000) | audio_gain_data; + atv_dmd_wr_word(APB_BLOCK_ADDR_MONO_PROC, 0x52, temp_data); +} + +unsigned int aml_audio_valume_gain_get(void) +{ + unsigned long audio_gain_data; + + audio_gain_data = atv_dmd_rd_word(APB_BLOCK_ADDR_MONO_PROC, 0x52); + audio_gain_data = audio_gain_data & 0xfff; + return audio_gain_data; +} + +void aml_atvdemod_overmodule_det(void) +{ + unsigned long temp_data, temp_data2;/* , temp_data3, temp_data4; */ + unsigned long counter_report; + int carrier_lock_count = 0; + int vlock = 0; + + switch (audio_det_mode) { + case AUDIO_AUTO_DETECT: + aml_audiomode_autodet(NULL); + return; +#if 0 + while (1) { + retrieve_vpll_carrier_lock(&vlock); + if (vlock) + break; + carrier_lock_count++; + if (carrier_lock_count >= 1000) + return; + /* ------------whether need timer delays between the detect lock---- */ + } + /* -----------------enable auto_adjust_en------------- */ + temp_data = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data | 0x100; + /* set the bit 9 of the temp_data to 1 */ + atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + /* -----------------enable auto_adjust_en end----------------- */ + /* -----------------begain to set ov_cnt_en enable------------- */ + temp_data2 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data2 = temp_data2 | 0x80; + /* set the bit 8 of the temp_data to 1 */ + atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data2); + /* ------------------set ov_cnt_en enable end---------------- */ + udelay(1000);/* timer delay needed , */ + /* ------------------------------------------------------------ */ + /* -----------------disable auto_adjust_en------------- */ + temp_data3 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data3 = temp_data3 & 0xfeff; + /* set the bit 9 of the temp_data to 0 */ + atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data3); + /* -----------------disable auto_adjust_en end------------ */ + /* -----------------begain to set ov_cnt_en disable------------- */ + temp_data4 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data4 = temp_data4 & 0xff7f; + /* set the bit 8 of the temp_data to 0 */ + atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data4); + break; + /* ------------------set ov_cnt_en disable end------ */ +#endif + case AUDIO_MANUAL_DETECT: + while (1) { + retrieve_vpll_carrier_lock(&vlock); + if (vlock) + break; + carrier_lock_count++; + if (carrier_lock_count >= 1000) + return; + } + + /* -----------------begain to set ov_cnt_en enable---- */ + temp_data = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data = temp_data | 0x80; + /* set the bit 8 of the temp_data to 1 */ + atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + /* ------------------set ov_cnt_en enable end--------------- */ + /* -----------------disable auto_adjust_en------------- */ + temp_data2 = atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + temp_data2 = temp_data2 & 0xfeff; + /* set the bit 9 of the temp_data to 0 */ + atv_dmd_wr_word(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data2); + /* -----------------disable auto_adjust_en end------------ */ + udelay(1000);/* timer delay needed , */ + /* ------------------------------------------------------- */ + counter_report = + atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x04); + + while (counter_report > over_threshold) { + + unsigned long shift_gain, shift_gain_report; + + temp_data2 = atv_dmd_rd_byte( + APB_BLOCK_ADDR_SIF_STG_2, 0x00); + shift_gain = temp_data2 & 0x07; + shift_gain--; + temp_data2 = (temp_data2 & 0xf8) | shift_gain; + atv_dmd_wr_byte(APB_BLOCK_ADDR_SIF_STG_2, 0x00, + temp_data2); + shift_gain_report = ( + (atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x04) + & 0x00070000) >> 16); + + if (shift_gain_report != shift_gain) + pr_info("[atvdemo...]:set shift_gain error\n"); + /* ------------------timer delay needed- */ + udelay(1000);/* timer delay needed , */ + /* ----------------------- */ + counter_report = + atv_dmd_rd_word(APB_BLOCK_ADDR_SIF_STG_2, 0x04); + } + break; + default: + pr_info("invalid over_module_det mode!!!\n"); + break; + } +} + +void aml_fix_PWM_adjust(int enable) +{ + unsigned long temp_data; + /* + * temp_data = atv_dmd_rd_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08); + * temp_data = temp_data | 0x01; + * atv_dmd_wr_byte(APB_BLOCK_ADDR_AGC_PWM, 0x08, temp_data); + */ + temp_data = atv_dmd_rd_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02); + if (enable) + temp_data = temp_data & ~((0x3)<<8); + else + temp_data = temp_data & ~((0x1)<<9); + + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + if (enable) { + temp_data = temp_data | ((0x3)<<8); + atv_dmd_wr_reg(APB_BLOCK_ADDR_SIF_STG_2, 0x02, temp_data); + } +} + +void aml_audio_overmodulation(int enable) +{ + static int ov_flag; + unsigned long tmp_v; + unsigned long tmp_v1; + u32 Broadcast_Standard = broad_std; + + if (enable && Broadcast_Standard == + AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK) { + tmp_v = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0x28); + tmp_v = tmp_v&0xffff; + if (tmp_v >= 0x10 && ov_flag == 0) { + tmp_v1 = + atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); + tmp_v1 = (tmp_v1&0xffffff)|(1<<24); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0x8000015); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x0f000); + } else if (tmp_v >= 0x2500 && ov_flag == 0) { + tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); + tmp_v1 = (tmp_v1&0xffffff)|(1<<24); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0xf400015); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x18, 0xc000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x0f000); + ov_flag = 1; + } else if (tmp_v <= 0x10 && ov_flag == 1) { + tmp_v1 = atv_dmd_rd_long(APB_BLOCK_ADDR_SIF_STG_2, 0); + tmp_v1 = (tmp_v1&0xffffff)|(0<<24); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, 0, tmp_v1); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x14, 0xf400000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x18, 0xc000); + atv_dmd_wr_long(APB_BLOCK_ADDR_SIF_STG_2, + 0x1c, 0x1f000); + ov_flag = 0; + } + } +} + +int amlatvdemod_reg_read(unsigned int reg, unsigned int *val) +{ + int ret = 0; + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + amlatvdemod_hiu_reg_read(HHI_GCLK_MPEG0, &ret); + if (0 == ((1<<29) & ret)) { + pr_err("%s GCLK_MPEG0:0x%x\n", __func__, ret); + return 0; + } + } else if (0 == (ADC_EN_ATV_DEMOD & tvafe_adc_get_pll_flag())) { + pr_info("%s atv demod pll not init\n", __func__); + return 0; + } + + *val = readl(amlatvdemod_devp->demod_reg_base + reg); + return 0; +} + +int amlatvdemod_reg_write(unsigned int reg, unsigned int val) +{ + int ret = 0; + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + amlatvdemod_hiu_reg_read(HHI_GCLK_MPEG0, &ret); + if (0 == ((1<<29) & ret)) { + pr_err("%s GCLK_MPEG0:0x%x\n", __func__, ret); + return 0; + } + } else if (0 == (ADC_EN_ATV_DEMOD & tvafe_adc_get_pll_flag())) { + pr_info("%s atv demod pll not init\n", __func__); + return 0; + } + + writel(val, (amlatvdemod_devp->demod_reg_base + reg)); + return 0; +} + +int atvaudiodem_reg_read(unsigned int reg, unsigned int *val) +{ + int ret = 0; + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + amlatvdemod_hiu_reg_read(HHI_GCLK_MPEG0, &ret); + if (0 == ((1<<31) & ret)) { + pr_err("%s GCLK_MPEG0:0x%x\n", __func__, ret); + return 0; + } + } + + if (amlatvdemod_devp->audio_reg_base) + *val = readl(amlatvdemod_devp->audio_reg_base + reg); + + return 0; +} + +int atvaudiodem_reg_write(unsigned int reg, unsigned int val) +{ + int ret = 0; + + if (is_meson_txlx_cpu() || is_meson_txhd_cpu()) { + amlatvdemod_hiu_reg_read(HHI_GCLK_MPEG0, &ret); + if (0 == ((1<<31) & ret)) { + pr_err("%s GCLK_MPEG0:0x%x\n", __func__, ret); + return 0; + } + } + + if (amlatvdemod_devp->audio_reg_base) + writel(val, (amlatvdemod_devp->audio_reg_base + reg)); + + return 0; +} + +int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val) +{ + *val = readl(amlatvdemod_devp->hiu_reg_base + ((reg - 0x1000)<<2)); + return 0; +} + +int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val) +{ + writel(val, (amlatvdemod_devp->hiu_reg_base + ((reg - 0x1000)<<2))); + return 0; +} + +int amlatvdemod_periphs_reg_read(unsigned int reg, unsigned int *val) +{ + *val = readl(amlatvdemod_devp->periphs_reg_base + ((reg - 0x1000)<<2)); + return 0; +} + +int amlatvdemod_periphs_reg_write(unsigned int reg, unsigned int val) +{ + writel(val, (amlatvdemod_devp->periphs_reg_base + ((reg - 0x1000)<<2))); + return 0; +} diff --git a/drivers/amlogic/atv_demod/atvdemod_func.h b/drivers/amlogic/atv_demod/atvdemod_func.h new file mode 100644 index 000000000000..3272e228019d --- /dev/null +++ b/drivers/amlogic/atv_demod/atvdemod_func.h @@ -0,0 +1,323 @@ +/* + * ATVDEMOD Device Driver + * + * Author: dezhi kong + * + * + * Copyright (C) 2014 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ATVDEMOD_FUN_H +#define __ATVDEMOD_FUN_H + +/*#include "../aml_fe.h"*/ +/*#include */ +/*#include "../aml_fe.h"*/ +#include + +struct dvb_frontend; + +/*#define TVFE_APB_BASE_ADDR 0xd0046000*/ +#define ATV_DMD_APB_BASE_ADDR 0xc8008000 +#define ATV_DMD_APB_BASE_ADDR_GXTVBB 0xc8840000 + +#define HHI_ATV_DMD_SYS_CLK_CNTL 0x10f3 + +extern int atvdemod_debug_en; +extern unsigned int reg_23cf; /* IIR filter */ +extern int broad_std_except_pal_m; + +#define ATVDEMOD_INTERVAL (HZ/100) /*10ms, #define HZ 100*/ + +extern int amlatvdemod_reg_read(unsigned int reg, unsigned int *val); +extern int amlatvdemod_reg_write(unsigned int reg, unsigned int val); +extern int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val); +extern int amlatvdemod_hiu_reg_write(unsigned int reg, unsigned int val); + +static inline uint32_t R_ATVDEMOD_REG(uint32_t reg) +{ + unsigned int val; + + amlatvdemod_reg_read(reg, &val); + return val; +} + +static inline void W_ATVDEMOD_REG(uint32_t reg, + const uint32_t val) +{ + amlatvdemod_reg_write(reg, val); +} + +static inline void W_ATVDEMOD_BIT(uint32_t reg, + const uint32_t value, + const uint32_t start, + const uint32_t len) +{ + W_ATVDEMOD_REG(reg, ((R_ATVDEMOD_REG(reg) & + ~(((1L << (len)) - 1) << (start))) | + (((value) & ((1L << (len)) - 1)) << (start)))); +} + +static inline uint32_t R_ATVDEMOD_BIT(uint32_t reg, + const uint32_t start, + const uint32_t len) +{ + uint32_t val; + + val = ((R_ATVDEMOD_REG(reg) >> (start)) & ((1L << (len)) - 1)); + + return val; +} + +static inline uint32_t R_HIU_REG(uint32_t reg) +{ + unsigned int val; + + amlatvdemod_hiu_reg_read(reg, &val); + return val; +} + +static inline void W_HIU_REG(uint32_t reg, + const uint32_t val) +{ + amlatvdemod_hiu_reg_write(reg, val); +} + +static inline void W_HIU_BIT(uint32_t reg, + const uint32_t value, + const uint32_t start, + const uint32_t len) +{ + W_HIU_REG(reg, ((R_HIU_REG(reg) & + ~(((1L << (len)) - 1) << (start))) | + (((value) & ((1L << (len)) - 1)) << (start)))); +} + +static inline uint32_t R_HIU_BIT(uint32_t reg, + const uint32_t start, + const uint32_t len) +{ + uint32_t val; + + val = ((R_HIU_REG(reg) >> (start)) & ((1L << (len)) - 1)); + + return val; +} + +enum broadcast_standard_e { + ATVDEMOD_STD_NTSC = 0, + ATVDEMOD_STD_NTSC_J, + ATVDEMOD_STD_PAL_M, + ATVDEMOD_STD_PAL_BG, + ATVDEMOD_STD_DTV, + ATVDEMOD_STD_SECAM_DK2, + ATVDEMOD_STD_SECAM_DK3, + ATVDEMOD_STD_PAL_BG_NICAM, + ATVDEMOD_STD_PAL_DK_CHINA, + ATVDEMOD_STD_SECAM_L, + ATVDEMOD_STD_PAL_I, + ATVDEMOD_STD_PAL_DK1, + ATVDEMOD_STD_MAX, +}; +enum gde_curve_e { + ATVDEMOD_CURVE_M = 0, + ATVDEMOD_CURVE_A, + ATVDEMOD_CURVE_B, + ATVDEMOD_CURVE_CHINA, + ATVDEMOD_CURVE_MAX, +}; +enum sound_format_e { + ATVDEMOD_SOUND_STD_MONO = 0, + ATVDEMOD_SOUND_STD_NICAM, + ATVDEMOD_SOUND_STD_MAX, +}; +extern void atv_dmd_wr_reg(unsigned char block, unsigned char reg, + unsigned long data); +extern unsigned long atv_dmd_rd_reg(unsigned char block, unsigned char reg); +extern unsigned long atv_dmd_rd_byte(unsigned long block_address, + unsigned long reg_addr); +extern unsigned long atv_dmd_rd_word(unsigned long block_address, + unsigned long reg_addr); +extern unsigned long atv_dmd_rd_long(unsigned long block_address, + unsigned long reg_addr); +extern void atv_dmd_wr_long(unsigned long block_address, + unsigned long reg_addr, + unsigned long data); +extern void atv_dmd_wr_word(unsigned long block_address, + unsigned long reg_addr, + unsigned long data); +extern void atv_dmd_wr_byte(unsigned long block_address, + unsigned long reg_addr, + unsigned long data); +extern void set_audio_gain_val(int val); +extern void set_video_gain_val(int val); +extern void atv_dmd_soft_reset(void); +extern void atv_dmd_input_clk_32m(void); +extern void read_version_register(void); +extern void check_communication_interface(void); +extern void power_on_receiver(void); +extern void atv_dmd_misc(void); +extern void configure_receiver(int Broadcast_Standard, + unsigned int Tuner_IF_Frequency, + int Tuner_Input_IF_inverted, int GDE_Curve, + int sound_format); +extern int atvdemod_clk_init(void); +extern int atvdemod_init(void); +extern void atvdemod_uninit(void); +extern void atv_dmd_set_std(void); +extern void retrieve_adc_power(int *adc_level); +extern void retrieve_vpll_carrier_lock(int *lock); +extern void retrieve_vpll_carrier_line_lock(int *lock); +extern void retrieve_vpll_carrier_audio_power(int *power); +extern void retrieve_video_lock(int *lock); +extern int retrieve_vpll_carrier_afc(void); + +extern int get_atvdemod_snr_val(void); +extern int aml_atvdemod_get_snr(struct dvb_frontend *fe); + +/*atv demod block address*/ +/*address interval is 4, because it's 32bit interface,*/ +/*but the address is in byte */ +#define ATV_DMD_TOP_CTRL 0x0 +#define ATV_DMD_TOP_CTRL1 0x4 +#define ATV_DMD_RST_CTRL 0x8 + +#define APB_BLOCK_ADDR_SYSTEM_MGT 0x0 +#define APB_BLOCK_ADDR_AA_LP_NOTCH 0x1 +#define APB_BLOCK_ADDR_MIXER_1 0x2 +#define APB_BLOCK_ADDR_MIXER_3 0x3 +#define APB_BLOCK_ADDR_ADC_SE 0x4 +#define APB_BLOCK_ADDR_PWR_ANL 0x5 +#define APB_BLOCK_ADDR_CARR_RCVY 0x6 +#define APB_BLOCK_ADDR_FE_DROOP_MDF 0x7 +#define APB_BLOCK_ADDR_SIF_IC_STD 0x8 +#define APB_BLOCK_ADDR_SIF_STG_2 0x9 +#define APB_BLOCK_ADDR_SIF_STG_3 0xa +#define APB_BLOCK_ADDR_IC_AGC 0xb +#define APB_BLOCK_ADDR_DAC_UPS 0xc +#define APB_BLOCK_ADDR_GDE_EQUAL 0xd +#define APB_BLOCK_ADDR_VFORMAT 0xe +#define APB_BLOCK_ADDR_VDAGC 0xf +#define APB_BLOCK_ADDR_VERS_REGISTER 0x10 +#define APB_BLOCK_ADDR_INTERPT_MGT 0x11 +#define APB_BLOCK_ADDR_ADC_MGR 0x12 +#define APB_BLOCK_ADDR_GP_VD_FLT 0x13 +#define APB_BLOCK_ADDR_CARR_DMD 0x14 +#define APB_BLOCK_ADDR_SIF_VD_IF 0x15 +#define APB_BLOCK_ADDR_VD_PKING 0x16 +#define APB_BLOCK_ADDR_FE_DR_SMOOTH 0x17 +#define APB_BLOCK_ADDR_AGC_PWM 0x18 +#define APB_BLOCK_ADDR_DAC_UPS_24M 0x19 +#define APB_BLOCK_ADDR_VFORMAT_DP 0x1a +#define APB_BLOCK_ADDR_VD_PKING_DAC 0x1b +#define APB_BLOCK_ADDR_MONO_PROC 0x1c +#define APB_BLOCK_ADDR_TOP 0x1d + +#define SLAVE_BLOCKS_NUMBER 0x1d /*indeed totals 0x1e, adding top*/ + +/*Broadcast_Standard*/ +/* 0: NTSC*/ +/* 1: NTSC-J*/ +/* 2: PAL-M,*/ +/* 3: PAL-BG*/ +/* 4: DTV*/ +/* 5: SECAM- DK2*/ +/* 6: SECAM -DK3*/ +/* 7: PAL-BG, NICAM*/ +/* 8: PAL-DK-CHINA*/ +/* 9: SECAM-L / SECAM-DK3*/ +/* 10: PAL-I*/ +/* 11: PAL-DK1*/ +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC 0 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_J 1 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_M 2 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG 3 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_DTV 4 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK2 5 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_DK3 6 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_BG_NICAM 7 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK 8 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L 9 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_I 10 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK1 11 +/* new add @20150813 begin */ +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_DK 12 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_BG 13 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_I 14 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC_M 15 +/* new add @20150813 end */ + +/*GDE_Curve*/ +/* 0: CURVE-M*/ +/* 1: CURVE-A*/ +/* 2: CURVE-B*/ +/* 3: CURVE-CHINA*/ +/* 4: BYPASS*/ +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_M 0 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_A 1 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_B 2 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_CHINA 3 +#define AML_ATV_DEMOD_VIDEO_MODE_PROP_CURVE_BYPASS 4 + +#define HHI_GCLK_MPEG0 (0x1050) + +/*sound format 0: MONO;1:NICAM*/ +#define AML_ATV_DEMOD_SOUND_MODE_PROP_MONO 0 +#define AML_ATV_DEMOD_SOUND_MODE_PROP_NICAM 1 +/* + * freq_hz:hs_freq + * freq_hz_cvrt=hs_freq/0.23841858 + * vs_freq==50,freq_hz=15625;freq_hz_cvrt=0xffff + * vs_freq==60,freq_hz=15734,freq_hz_cvrt=0x101c9 + */ +#define AML_ATV_DEMOD_FREQ_50HZ_VERT 0xffff /*65535*/ +#define AML_ATV_DEMOD_FREQ_60HZ_VERT 0x101c9 /*65993*/ + +#define CARR_AFC_DEFAULT_VAL 0xffff + +enum amlatvdemod_snr_level_e { + very_low = 1, + low, + ok_minus, + ok_plus, + high, +}; + +enum audio_detect_mode { + AUDIO_AUTO_DETECT = 0, + AUDIO_MANUAL_DETECT, +}; + +#if 0 +struct amlatvdemod_device_s { + struct class *clsp; + struct device *dev; + struct analog_parameters parm; + int fre_offset; + struct pinctrl *pin; + const char *pin_name; +}; +#endif + +extern int amlatvdemod_hiu_reg_read(unsigned int reg, unsigned int *val); +extern void aml_audio_overmodulation(int enable); +extern void amlatvdemod_set_std(int val); +extern void aml_fix_PWM_adjust(int enable); +extern void aml_audio_valume_gain_set(unsigned int audio_gain); +extern unsigned int aml_audio_valume_gain_get(void); +extern void aml_atvdemod_overmodule_det(void); +extern int aml_audiomode_autodet(struct dvb_frontend *fe); +extern void retrieve_frequency_offset(int *freq_offset); +extern void retrieve_field_lock(int *lock); +extern int aml_atvdemod_get_snr_ex(void); +extern void set_atvdemod_scan_mode(int val); +extern int atvauddemod_init(void); +extern void atvauddemod_set_outputmode(void); + +/*from amldemod/amlfrontend.c*/ +extern int vdac_enable_check_dtv(void); +#endif /* __ATVDEMOD_FUN_H */ diff --git a/drivers/amlogic/atv_demod/aud_demod_reg.h b/drivers/amlogic/atv_demod/aud_demod_reg.h new file mode 100644 index 000000000000..73a36e290091 --- /dev/null +++ b/drivers/amlogic/atv_demod/aud_demod_reg.h @@ -0,0 +1,337 @@ +#ifndef AUD_DEMOD_REG_H + +#define AUD_DEMOD_REG_H + +#define ADEC_CTRL 0x010 +#define FREQ0_CTRL 0x011 +#define FREQ1_CTRL 0x012 +#define ID_FREQ_STEREO_CTRL 0x013 +#define ID_FREQ_DUAL_CTRL 0x014 +#define ID_FREQ_CARRIER_CTRL 0x015 +#define DEMOD_GAIN_CTRL 0x016 +#define BTSC_BYPASS_CTRL 0x017 +#define EXPANDER_SPEC_ADJ 0x018 +#define EXPANDER_GAIN_ADJ 0x019 +#define LMR_GAIN_ADJ 0x01a +#define SAP_GAIN_ADJ 0x01b +#define LPR_GAIN_ADJ 0x01c +#define BTSC_STEREO_THD 0x01d +#define DELAY_COMP_CRTL 0x01e +#define EXPANDER_B_CTRL 0x01f +#define EXPANDER_B2C_ADJ 0x020 +#define TEST_SEL_CTRL 0x021 +#define IIR_SPEED_CTRL 0x022 +#define STEREO_DET_THD 0x023 +#define DUAL_DET_THD 0x024 +#define SAP_DET_THD 0x025 +#define MODE_DET_CNT_THD 0x026 +#define ADEC_RESET 0x027 + +#define DDC_FIR_COEF0_0 0x030 +#define DDC_FIR_COEF0_1 0x031 +#define DDC_FIR_COEF0_2 0x032 +#define DDC_FIR_COEF0_3 0x033 +#define DDC_FIR_COEF0_4 0x034 +#define DDC_FIR_COEF0_5 0x035 +#define DDC_FIR_COEF0_6 0x036 +#define DDC_FIR_COEF0_7 0x037 +#define DDC_FIR_COEF0_8 0x038 +#define DDC_FIR_COEF0_9 0x039 +#define DDC_FIR_COEF0_10 0x03a +#define DDC_FIR_COEF0_11 0x03b +#define DDC_FIR_COEF0_12 0x03c +#define DDC_FIR_COEF0_13 0x03d +#define DDC_FIR_COEF0_14 0x03e +#define DDC_FIR_COEF0_15 0x03f +#define DDC_FIR_COEF0_16 0x040 +#define DDC_FIR_COEF1_0 0x041 +#define DDC_FIR_COEF1_1 0x042 +#define DDC_FIR_COEF1_2 0x043 +#define DDC_FIR_COEF1_3 0x044 +#define DDC_FIR_COEF1_4 0x045 +#define DDC_FIR_COEF1_5 0x046 +#define DDC_FIR_COEF1_6 0x047 +#define DDC_FIR_COEF1_7 0x048 +#define DDC_FIR_COEF1_8 0x049 +#define DDC_FIR_COEF1_9 0x04a +#define DDC_FIR_COEF1_10 0x04b +#define DDC_FIR_COEF1_11 0x04c +#define DDC_FIR_COEF1_12 0x04d +#define DDC_FIR_COEF1_13 0x04e +#define DDC_FIR_COEF1_14 0x04f +#define DDC_FIR_COEF1_15 0x050 +#define DDC_FIR_COEF1_16 0x051 +#define FILTER_00_0 0x052 +#define FILTER_00_1 0x053 +#define FILTER_00_2 0x054 +#define FILTER_01_0 0x055 +#define FILTER_01_1 0x056 +#define FILTER_01_2 0x057 +#define FILTER_02_0 0x058 +#define FILTER_02_1 0x059 +#define FILTER_02_2 0x05a +#define FILTER_03_0 0x05b +#define FILTER_03_1 0x05c +#define FILTER_03_2 0x05d +#define FILTER_04_0 0x05e +#define FILTER_04_1 0x05f +#define FILTER_04_2 0x060 +#define FILTER_05_0 0x061 +#define FILTER_05_1 0x062 +#define FILTER_05_2 0x063 +#define FILTER_06_0 0x064 +#define FILTER_06_1 0x065 +#define FILTER_06_2 0x066 +#define FILTER_07_0 0x067 +#define FILTER_07_1 0x068 +#define FILTER_07_2 0x069 +#define FILTER_08_0 0x06a +#define FILTER_08_1 0x06b +#define FILTER_08_2 0x06c +#define FILTER_09_0 0x06d +#define FILTER_09_1 0x06e +#define FILTER_09_2 0x06f +#define FILTER_10_0 0x070 +#define FILTER_10_1 0x071 +#define FILTER_10_2 0x072 +#define FILTER_11_0 0x073 +#define FILTER_11_1 0x074 +#define FILTER_11_2 0x075 +#define FILTER_12_0 0x076 +#define FILTER_12_1 0x077 +#define FILTER_12_2 0x078 +#define FILTER_13_0 0x079 +#define FILTER_13_1 0x07a +#define FILTER_13_2 0x07b +#define FILTER_14_0 0x07c +#define FILTER_14_1 0x07d +#define FILTER_14_2 0x07e +#define FILTER_15_0 0x07f +#define FILTER_15_1 0x080 +#define FILTER_15_2 0x081 + +#define DBX_FILTER_01_0 0x085 +#define DBX_FILTER_01_1 0x086 +#define DBX_FILTER_01_2 0x087 +#define DBX_FILTER_02_0 0x088 +#define DBX_FILTER_02_1 0x089 +#define DBX_FILTER_02_2 0x08a +#define DBX_FILTER_03_0 0x08b +#define DBX_FILTER_03_1 0x08c +#define DBX_FILTER_03_2 0x08d +#define DBX_FILTER_04_0 0x08e +#define DBX_FILTER_04_1 0x08f +#define DBX_FILTER_04_2 0x090 +#define DBX_FILTER_05_0 0x091 +#define DBX_FILTER_05_1 0x092 +#define DBX_FILTER_05_2 0x093 +#define DBX_FILTER_06_0 0x094 +#define DBX_FILTER_06_1 0x095 +#define DBX_FILTER_06_2 0x096 +#define DBX_FILTER_07_0 0x097 +#define DBX_FILTER_07_1 0x098 +#define DBX_FILTER_07_2 0x099 +#define DBX_FILTER_08_0 0x09a +#define DBX_FILTER_08_1 0x09b +#define DBX_FILTER_08_2 0x09c + +#define BB_COEF0_A_0 0x0a0 +#define BB_COEF0_A_1 0x0a1 +#define BB_COEF0_A_2 0x0a2 +#define BB_COEF0_A_3 0x0a3 +#define BB_COEF1_A_0 0x0a4 +#define BB_COEF1_A_1 0x0a5 +#define BB_COEF1_A_2 0x0a6 +#define BB_COEF1_A_3 0x0a7 +#define BB_COEF2_A_0 0x0a8 +#define BB_COEF2_A_1 0x0a9 +#define BB_COEF2_A_2 0x0aa +#define BB_COEF2_A_3 0x0ab +#define BB_COEF0_B_0 0x0ac +#define BB_COEF0_B_1 0x0ad +#define BB_COEF0_B_2 0x0ae +#define BB_COEF0_B_3 0x0af +#define BB_COEF1_B_0 0x0b0 +#define BB_COEF1_B_1 0x0b1 +#define BB_COEF1_B_2 0x0b2 +#define BB_COEF1_B_3 0x0b3 +#define BB_COEF2_B_0 0x0b4 +#define BB_COEF2_B_1 0x0b5 +#define BB_COEF2_B_2 0x0b6 +#define BB_COEF2_B_3 0x0b7 +#define MUTE_THD0 0x0b8 +#define MUTE_THD1 0x0b9 +#define MUTE_THD2 0x0ba +#define NOISE_THD0 0x0bb +#define NOISE_THD1 0x0bc +#define NOISE_THD2 0x0bd +#define BB_SPEED 0x0be +#define SRC_CTRL0 0x0c0 +#define SRC_CTRL1 0x0c1 +#define SRC_CTRL2 0x0c2 +#define SRC_CTRL3 0x0c3 +#define SRC_CTRL4 0x0c4 +#define SRC_CTRL5 0x0c5 +#define SRC_CTRL6 0x0c6 +#define SRC_CTRL7 0x0c7 +#define SRC_CTRL8 0x0c8 +#define SRC_CTRL9 0x0c9 +#define THD_P0 0x0d0 +#define THD_M0 0x0d1 +#define THD_OV0 0x0d2 +#define THD_CNT0 0x0d3 +#define CNT_MAX0 0x0d4 +#define THD_P1 0x0d5 +#define THD_M1 0x0d6 +#define THD_OV1 0x0d7 +#define THD_CNT1 0x0d8 +#define CNT_MAX1 0x0d9 + +#define OV_CNT_REPORT 0x0da +#define OV_FLAG_REPORT 0x0db + +#define PILOT_BIAS_REPORT 0x0f0 +#define STEREO_LEVEL_REPORT 0x0f1 +#define SNR_REPORT 0x0f2 +#define SNR_SAP_REPORT 0x0f3 +#define POWER_REPORT 0x0f4 +#define DC_REPORT 0x0f5 +#define CARRIER_MAG_REPORT 0x0f6 +#define BTSC_AB_REPORT 0x0f7 +#define AUDIO_MODE_REPORT 0x0f8 + +#define CTRL_SEL 0x0ff + +#define FCLK 32e6 +#define ADDR_ADEC_CTRL (ADEC_CTRL) + +#define ADDR_BTSC_BYPASS_CTRL (BTSC_BYPASS_CTRL) +#define ADDR_EXPANDER_SPECTRAL_ADJ (EXPANDER_SPEC_ADJ) +#define ADDR_EXPANDER_GAIN_ADJ (EXPANDER_GAIN_ADJ) +#define ADDR_LMR_ADJ (LMR_GAIN_ADJ) +#define ADDR_SAP_ADJ (SAP_GAIN_ADJ) +#define ADDR_LPR_GAIN_ADJ (LPR_GAIN_ADJ) +#define ADDR_STEREO_THRESHOLD (BTSC_STEREO_THD) +#define ADDR_LPR_COMP_CTRL (DELAY_COMP_CRTL) +#define ADDR_EXPANDER_B_CTRL (EXPANDER_B_CTRL) +#define ADDR_EXPANDER_B2C_ADJ (EXPANDER_B2C_ADJ) +#define ADDR_TEST_SEL_CTRL (TEST_SEL_CTRL) + +#define ADDR_SAP_FIR_COEF (DDC_FIR_COEF1_0) + +#define ADDR_SAP_DTO (FREQ1_CTRL) + +#define ADDR_DDC_FREQ0 (FREQ0_CTRL) +#define ADDR_DDC_FREQ1 (FREQ1_CTRL) + +#define ADDR_DEMOD_GAIN (DEMOD_GAIN_CTRL) + + +#define ADDR_DDC_FIR0_COEF (DDC_FIR_COEF0_0) +#define ADDR_DDC_FIR1_COEF (DDC_FIR_COEF1_0) +#define ADDR_BB_FIR0_A_COEF (BB_COEF0_A_0) +#define ADDR_BB_FIR1_A_COEF (BB_COEF1_A_0) +#define ADDR_BB_FIR2_A_COEF (BB_COEF2_A_0) + +#define ADDR_BB_FIR0_B_COEF (BB_COEF0_B_0) +#define ADDR_BB_FIR1_B_COEF (BB_COEF0_B_1) +#define ADDR_BB_FIR2_B_COEF (BB_COEF0_B_2) + +#define ADDR_BB_MUTE_THRESHOLD0 (MUTE_THD0) +#define ADDR_BB_MUTE_THRESHOLD1 (MUTE_THD1) +#define ADDR_BB_MUTE_THRESHOLD2 (MUTE_THD2) + +#define ADDR_BB_NOISE_THRESHOLD0 (NOISE_THD0) +#define ADDR_BB_NOISE_THRESHOLD1 (NOISE_THD1) +#define ADDR_BB_NOISE_THRESHOLD2 (NOISE_THD2) + +#define ADDR_INDICATOR_STEREO_DTO (ID_FREQ_STEREO_CTRL) +#define ADDR_INDICATOR_DUAL_DTO (ID_FREQ_DUAL_CTRL) + +#define ADDR_INDICATOR_CENTER_DTO (ID_FREQ_CARRIER_CTRL) + +#define ADDR_IIR_LPR_15K_0 (FILTER_00_0) +#define ADDR_IIR_LPR_15K_1 (FILTER_01_0) +#define ADDR_IIR_LPR_15K_2 (FILTER_02_0) +#define ADDR_IIR_LPR_15K_3 (FILTER_03_0) +#define ADDR_IIR_LPR_15K_4 (FILTER_04_0) + +#define ADDR_IIR_LMR_15K_0 (FILTER_05_0) +#define ADDR_IIR_LMR_15K_1 (FILTER_06_0) +#define ADDR_IIR_LMR_15K_2 (FILTER_07_0) +#define ADDR_IIR_LMR_15K_3 (FILTER_08_0) +#define ADDR_IIR_LMR_15K_4 (FILTER_09_0) + +#define ADDR_IIR_LPR_DEEMPHASIS (FILTER_10_0) +#define ADDR_IIR_PILOT_0 (FILTER_11_0) +#define ADDR_IIR_PILOT_1 (FILTER_12_0) +#define ADDR_IIR_PILOT_2 (FILTER_13_0) +#define ADDR_IIR_LPR_COMP (FILTER_14_0) +#define ADDR_IIR_LMR_DEEMPHASIS (FILTER_15_0) + +#define ADDR_IIR_FIXED_DEEM_0 (DBX_FILTER_01_0) +#define ADDR_IIR_FIXED_DEEM_1 (DBX_FILTER_02_0) +#define ADDR_IIR_FIXED_DEEM_2 (DBX_FILTER_03_0) + +#define ADDR_IIR_Q_FILTER_0 (DBX_FILTER_04_0) +#define ADDR_IIR_Q_FILTER_1 (DBX_FILTER_05_0) +#define ADDR_IIR_Q_FILTER_2 (DBX_FILTER_06_0) +#define ADDR_IIR_P_FILTER_0 (DBX_FILTER_07_0) +#define ADDR_IIR_P_FILTER_1 (DBX_FILTER_08_0) + +#define ADDR_IIR_SPEED_CTRL (IIR_SPEED_CTRL) +#define ADDR_SEL_CTRL (CTRL_SEL) + + +#define AUDIO_STANDARD_BTSC 0x00 +#define AUDIO_STANDARD_EIAJ 0x01 +#define AUDIO_STANDARD_A2_K 0x02 +#define AUDIO_STANDARD_A2_BG 0x03 +#define AUDIO_STANDARD_A2_DK1 0x04 +#define AUDIO_STANDARD_A2_DK2 0x05 +#define AUDIO_STANDARD_A2_DK3 0x06 +#define AUDIO_STANDARD_NICAM_I 0x07 +#define AUDIO_STANDARD_NICAM_BG 0x08 +#define AUDIO_STANDARD_NICAM_L 0x09 +#define AUDIO_STANDARD_NICAM_DK 0x0A +#define AUDIO_STANDARD_FM_USA 0x0B +#define AUDIO_STANDARD_FM_EU 0x0C +#define AUDIO_STANDARD_CHINA 0x0E +#define AUDIO_STANDARD_INDIAN 0x0F +#define AUDIO_STANDARD_BTSC_SA 0x10 +#define AUDIO_STANDARD_MONO_ONLY 0x11 + +#define AUDIO_OUTMODE_MONO 0 +#define AUDIO_OUTMODE_STEREO 1 +#define AUDIO_OUTMODE_SAP_DUAL 2 + + +#define AUDIO_OUTMODE_BTSC_MONO 0 +#define AUDIO_OUTMODE_BTSC_STEREO 1 +#define AUDIO_OUTMODE_BTSC_SAP 2 + +#define AUDIO_OUTMODE_EIAJ_MONO 0 +#define AUDIO_OUTMODE_EIAJ_STEREO 1 +#define AUDIO_OUTMODE_EIAJ_MAIN 2 +#define AUDIO_OUTMODE_EIAJ_SUB 3 +#define AUDIO_OUTMODE_EIAJ_MAIN_SUB 4 + +#define AUDIO_OUTMODE_A2_MONO 0 +#define AUDIO_OUTMODE_A2_STEREO 1 +#define AUDIO_OUTMODE_A2_DUAL_A 2 +#define AUDIO_OUTMODE_A2_DUAL_B 3 +#define AUDIO_OUTMODE_A2_DUAL_AB 4 + +#define AUDIO_OUTMODE_NICAM_MONO 0 +#define AUDIO_OUTMODE_NICAM_MONO1 1 +#define AUDIO_OUTMODE_NICAM_STEREO 2 +#define AUDIO_OUTMODE_NICAM_DUAL_A 3 +#define AUDIO_OUTMODE_NICAM_DUAL_B 4 +#define AUDIO_OUTMODE_NICAM_DUAL_AB 5 + +#define AUDIO_DEEM_75US 0 +#define AUDIO_DEEM_50US 1 +#define AUDIO_DEEM_J17 2 + + +#endif diff --git a/drivers/amlogic/atv_demod/aud_demod_settings.c b/drivers/amlogic/atv_demod/aud_demod_settings.c new file mode 100644 index 000000000000..7f147c48e5a6 --- /dev/null +++ b/drivers/amlogic/atv_demod/aud_demod_settings.c @@ -0,0 +1,2862 @@ +#include "aud_demod_settings.h" + +int M_DTO = 0x170a3d; +int A2K_DTO = 0x049784; +int BG_DTO = 0x1c28f6; +int A2G_DTO = 0x04f5c3; +int EIAJ_DTO = 0x13557d; +int SAP_DTO = 0x203926; +int A2K_STEREO_DTO = 0x169e37; +int A2K_DUAL_DTO = 0x16ab71; +int A2K_INDICATOR_DTO = 0x168e7f; +int A2G_STEREO_DTO = 0x1672b9; +int A2G_DUAL_DTO = 0x168324; +int A2G_INDICATOR_DTO = 0x166666; +int filter_25k[] = { + 0x0015, + 0x0018, + 0x001e, + 0x0025, + 0x002f, + 0x003c, + 0x004d, + 0x0061, + 0x0079, + 0x0095, + 0x00b5, + 0x00da, + 0x0102, + 0x012f, + 0x015e, + 0x0192, + 0x01c7, + 0x01ff, + 0x0238, + 0x0273, + 0x02ad, + 0x02e6, + 0x031e, + 0x0353, + 0x0386, + 0x03b4, + 0x03de, + 0x0403, + 0x0421, + 0x043a, + 0x044c, + 0x0456, + 0x045a, + 0x0456, + 0x044c, + 0x043a, + 0x0421, + 0x0403, + 0x03de, + 0x03b4, + 0x0386, + 0x0353, + 0x031e, + 0x02e6, + 0x02ad, + 0x0273, + 0x0238, + 0x01ff, + 0x01c7, + 0x0192, + 0x015e, + 0x012f, + 0x0102, + 0x00da, + 0x00b5, + 0x0095, + 0x0079, + 0x0061, + 0x004d, + 0x003c, + 0x002f, + 0x0025, + 0x001e, + 0x0018, + 0x0015, +}; +int filter_50k[] = { + 0xffe7, + 0xffe4, + 0xffe1, + 0xffdc, + 0xffd7, + 0xffd1, + 0xffcc, + 0xffc9, + 0xffc9, + 0xffcc, + 0xffd6, + 0xffe7, + 0x0000, + 0x0023, + 0x0051, + 0x008b, + 0x00d1, + 0x0122, + 0x017f, + 0x01e6, + 0x0255, + 0x02cb, + 0x0346, + 0x03c1, + 0x043b, + 0x04b0, + 0x051d, + 0x0580, + 0x05d5, + 0x061a, + 0x064c, + 0x066b, + 0x0676, + 0x066b, + 0x064c, + 0x061a, + 0x05d5, + 0x0580, + 0x051d, + 0x04b0, + 0x043b, + 0x03c1, + 0x0346, + 0x02cb, + 0x0255, + 0x01e6, + 0x017f, + 0x0122, + 0x00d1, + 0x008b, + 0x0051, + 0x0023, + 0x0000, + 0xffe7, + 0xffd6, + 0xffcc, + 0xffc9, + 0xffc9, + 0xffcc, + 0xffd1, + 0xffd7, + 0xffdc, + 0xffe1, + 0xffe4, + 0xffe7, +}; +int filter_75k[] = { + 0x0019, + 0x0018, + 0x0016, + 0x0013, + 0x000d, + 0x0004, + 0xfff6, + 0xffe3, + 0xffc9, + 0xffab, + 0xff88, + 0xff64, + 0xff43, + 0xff28, + 0xff18, + 0xff1a, + 0xff32, + 0xff65, + 0xffb7, + 0x002a, + 0x00c0, + 0x0176, + 0x0249, + 0x0334, + 0x042e, + 0x052f, + 0x062c, + 0x071a, + 0x07ee, + 0x08a0, + 0x0925, + 0x0977, + 0x0993, + 0x0977, + 0x0925, + 0x08a0, + 0x07ee, + 0x071a, + 0x062c, + 0x052f, + 0x042e, + 0x0334, + 0x0249, + 0x0176, + 0x00c0, + 0x002a, + 0xffb7, + 0xff65, + 0xff32, + 0xff1a, + 0xff18, + 0xff28, + 0xff43, + 0xff64, + 0xff88, + 0xffab, + 0xffc9, + 0xffe3, + 0xfff6, + 0x0004, + 0x000d, + 0x0013, + 0x0016, + 0x0018, + 0x0019, +}; +int filter_100k[] = { + 0xfff1, + 0xfff7, + 0x0000, + 0x000b, + 0x0019, + 0x002a, + 0x003c, + 0x004d, + 0x0059, + 0x005b, + 0x004f, + 0x0032, + 0x0000, + 0xffbb, + 0xff67, + 0xff0b, + 0xfeb2, + 0xfe6a, + 0xfe42, + 0xfe4b, + 0xfe93, + 0xff22, + 0x0000, + 0x012a, + 0x0296, + 0x0436, + 0x05f4, + 0x07b3, + 0x0957, + 0x0ac2, + 0x0bdb, + 0x0c8d, + 0x0cc9, + 0x0c8d, + 0x0bdb, + 0x0ac2, + 0x0957, + 0x07b3, + 0x05f4, + 0x0436, + 0x0296, + 0x012a, + 0x0000, + 0xff22, + 0xfe93, + 0xfe4b, + 0xfe42, + 0xfe6a, + 0xfeb2, + 0xff0b, + 0xff67, + 0xffbb, + 0x0000, + 0x0032, + 0x004f, + 0x005b, + 0x0059, + 0x004d, + 0x003c, + 0x002a, + 0x0019, + 0x000b, + 0x0000, + 0xfff7, + 0xfff1, +}; +int filter_125k[] = { + 0x0000, + 0xfff5, + 0xffea, + 0xffdf, + 0xffd5, + 0xffd0, + 0xffd3, + 0xffe2, + 0x0000, + 0x002b, + 0x0060, + 0x0095, + 0x00be, + 0x00cf, + 0x00b9, + 0x0074, + 0x0000, + 0xff64, + 0xfeb3, + 0xfe0b, + 0xfd90, + 0xfd67, + 0xfdb4, + 0xfe8e, + 0x0000, + 0x0200, + 0x0471, + 0x0723, + 0x09db, + 0x0c54, + 0x0e50, + 0x0f99, + 0x100a, + 0x0f99, + 0x0e50, + 0x0c54, + 0x09db, + 0x0723, + 0x0471, + 0x0200, + 0x0000, + 0xfe8e, + 0xfdb4, + 0xfd67, + 0xfd90, + 0xfe0b, + 0xfeb3, + 0xff64, + 0x0000, + 0x0074, + 0x00b9, + 0x00cf, + 0x00be, + 0x0095, + 0x0060, + 0x002b, + 0x0000, + 0xffe2, + 0xffd3, + 0xffd0, + 0xffd5, + 0xffdf, + 0xffea, + 0xfff5, + 0x0000, +}; +int filter_150k[] = { + 0x000f, + 0x0019, + 0x001f, + 0x0020, + 0x0019, + 0x0008, + 0xffed, + 0xffca, + 0xffa7, + 0xff91, + 0xff93, + 0xffb7, + 0x0000, + 0x0065, + 0x00d3, + 0x012b, + 0x014e, + 0x011f, + 0x0091, + 0xffac, + 0xfe93, + 0xfd82, + 0xfcc4, + 0xfca7, + 0xfd6a, + 0xff30, + 0x01ee, + 0x0570, + 0x0953, + 0x0d1e, + 0x104c, + 0x1269, + 0x1327, + 0x1269, + 0x104c, + 0x0d1e, + 0x0953, + 0x0570, + 0x01ee, + 0xff30, + 0xfd6a, + 0xfca7, + 0xfcc4, + 0xfd82, + 0xfe93, + 0xffac, + 0x0091, + 0x011f, + 0x014e, + 0x012b, + 0x00d3, + 0x0065, + 0x0000, + 0xffb7, + 0xff93, + 0xff91, + 0xffa7, + 0xffca, + 0xffed, + 0x0008, + 0x0019, + 0x0020, + 0x001f, + 0x0019, + 0x000f, +}; +int filter_200k[] = { + 0x0019, + 0x0010, + 0x0000, + 0xffeb, + 0xffd7, + 0xffcf, + 0xffdb, + 0x0000, + 0x0037, + 0x006b, + 0x0080, + 0x005e, + 0x0000, + 0xff7d, + 0xff08, + 0xfedf, + 0xff31, + 0x0000, + 0x0114, + 0x0202, + 0x0250, + 0x01a6, + 0x0000, + 0xfdc9, + 0xfbcf, + 0xfb0b, + 0xfc51, + 0x0000, + 0x05c7, + 0x0ca9, + 0x1334, + 0x17e5, + 0x1999, + 0x17e5, + 0x1334, + 0x0ca9, + 0x05c7, + 0x0000, + 0xfc51, + 0xfb0b, + 0xfbcf, + 0xfdc9, + 0x0000, + 0x01a6, + 0x0250, + 0x0202, + 0x0114, + 0x0000, + 0xff31, + 0xfedf, + 0xff08, + 0xff7d, + 0x0000, + 0x005e, + 0x0080, + 0x006b, + 0x0037, + 0x0000, + 0xffdb, + 0xffcf, + 0xffd7, + 0xffeb, + 0x0000, + 0x0010, + 0x0019, +}; +int filter_300k[] = { + 0xffe7, + 0xffea, + 0x0000, + 0x001d, + 0x0029, + 0x0010, + 0xffdb, + 0xffb3, + 0xffc9, + 0x0023, + 0x0080, + 0x0082, + 0x0000, + 0xff4b, + 0xff08, + 0xffa2, + 0x00cf, + 0x0197, + 0x0114, + 0xff59, + 0xfdaf, + 0xfdbb, + 0x0000, + 0x030d, + 0x0432, + 0x019d, + 0xfc50, + 0xf849, + 0xfa37, + 0x041e, + 0x133a, + 0x20ed, + 0x2672, + 0x20ed, + 0x133a, + 0x041e, + 0xfa37, + 0xf849, + 0xfc50, + 0x019d, + 0x0432, + 0x030d, + 0x0000, + 0xfdbb, + 0xfdaf, + 0xff59, + 0x0114, + 0x0197, + 0x00cf, + 0xffa2, + 0xff08, + 0xff4b, + 0x0000, + 0x0082, + 0x0080, + 0x0023, + 0xffc9, + 0xffb3, + 0xffdb, + 0x0010, + 0x0029, + 0x001d, + 0x0000, + 0xffea, + 0xffe7, +}; +int filter_400k[] = { + 0x000f, + 0x001a, + 0x0000, + 0xffde, + 0xffe7, + 0x001e, + 0x003c, + 0x0000, + 0xffa7, + 0xffbe, + 0x004f, + 0x0098, + 0x0000, + 0xff2c, + 0xff67, + 0x00b2, + 0x014e, + 0x0000, + 0xfe42, + 0xfec3, + 0x016d, + 0x02aa, + 0x0000, + 0xfc6c, + 0xfd6a, + 0x030f, + 0x05f3, + 0x0000, + 0xf6aa, + 0xf82f, + 0x0bda, + 0x269d, + 0x3322, + 0x269d, + 0x0bda, + 0xf82f, + 0xf6aa, + 0x0000, + 0x05f3, + 0x030f, + 0xfd6a, + 0xfc6c, + 0x0000, + 0x02aa, + 0x016d, + 0xfec3, + 0xfe42, + 0x0000, + 0x014e, + 0x00b2, + 0xff67, + 0xff2c, + 0x0000, + 0x0098, + 0x004f, + 0xffbe, + 0xffa7, + 0x0000, + 0x003c, + 0x001e, + 0xffe7, + 0xffde, + 0x0000, + 0x001a, + 0x000f, +}; +int filter_550k[] = { + 0xffe7, + 0xfffc, + 0x001f, + 0xfffa, + 0xffd7, + 0x0018, + 0x0033, + 0xffca, + 0xffc9, + 0x0064, + 0x002a, + 0xff61, + 0x0000, + 0x00dd, + 0xffaf, + 0xfef1, + 0x00cf, + 0x0120, + 0xfe84, + 0xff0a, + 0x0250, + 0x0070, + 0xfcc1, + 0x0097, + 0x0432, + 0xfda2, + 0xfaed, + 0x0574, + 0x05c8, + 0xf421, + 0xf9c1, + 0x2831, + 0x4677, + 0x2831, + 0xf9c1, + 0xf421, + 0x05c8, + 0x0574, + 0xfaed, + 0xfda2, + 0x0432, + 0x0097, + 0xfcc1, + 0x0070, + 0x0250, + 0xff0a, + 0xfe84, + 0x0120, + 0x00cf, + 0xfef1, + 0xffaf, + 0x00dd, + 0x0000, + 0xff61, + 0x002a, + 0x0064, + 0xffc9, + 0xffca, + 0x0033, + 0x0018, + 0xffd7, + 0xfffa, + 0x001f, + 0xfffc, + 0xffe7, +}; +int filter_sap_10k[] = { + 0x001a, + 0x001c, + 0x001d, + 0x001e, + 0x001d, + 0x0019, + 0x0010, + 0x0000, + 0xffe9, + 0xffca, + 0xffa4, + 0xff79, + 0xff4c, + 0xff22, + 0xff00, + 0xfeee, + 0xfef1, + 0xff11, + 0xff54, + 0xffbc, + 0x004e, + 0x0108, + 0x01e7, + 0x02e5, + 0x03fb, + 0x051c, + 0x063d, + 0x0750, + 0x0848, + 0x0918, + 0x09b5, + 0x0a16, + 0x0a38, + 0x0a16, + 0x09b5, + 0x0918, + 0x0848, + 0x0750, + 0x063d, + 0x051c, + 0x03fb, + 0x02e5, + 0x01e7, + 0x0108, + 0x004e, + 0xffbc, + 0xff54, + 0xff11, + 0xfef1, + 0xfeee, + 0xff00, + 0xff22, + 0xff4c, + 0xff79, + 0xffa4, + 0xffca, + 0xffe9, + 0x0000, + 0x0010, + 0x0019, + 0x001d, + 0x001e, + 0x001d, + 0x001c, + 0x001a, +}; +int filter_sap_15k[] = { + 0xfff3, + 0xffeb, + 0xffe3, + 0xffdc, + 0xffd9, + 0xffdc, + 0xffe9, + 0x0000, + 0x0022, + 0x004d, + 0x007a, + 0x00a1, + 0x00b5, + 0x00ac, + 0x007e, + 0x0026, + 0xffa8, + 0xff10, + 0xfe73, + 0xfdec, + 0xfd9b, + 0xfda0, + 0xfe17, + 0xff10, + 0x008e, + 0x0285, + 0x04d7, + 0x0759, + 0x09d6, + 0x0c14, + 0x0ddc, + 0x0f01, + 0x0f66, + 0x0f01, + 0x0ddc, + 0x0c14, + 0x09d6, + 0x0759, + 0x04d7, + 0x0285, + 0x008e, + 0xff10, + 0xfe17, + 0xfda0, + 0xfd9b, + 0xfdec, + 0xfe73, + 0xff10, + 0xffa8, + 0x0026, + 0x007e, + 0x00ac, + 0x00b5, + 0x00a1, + 0x007a, + 0x004d, + 0x0022, + 0x0000, + 0xffe9, + 0xffdc, + 0xffd9, + 0xffdc, + 0xffe3, + 0xffeb, + 0xfff3, +}; +int filter_sap_20k[] = { + 0xfff6, + 0x0003, + 0x0012, + 0x0020, + 0x002b, + 0x002c, + 0x001e, + 0x0000, + 0xffd3, + 0xffa1, + 0xff7a, + 0xff6f, + 0xff91, + 0xffe4, + 0x0060, + 0x00ea, + 0x0159, + 0x0182, + 0x0141, + 0x0086, + 0xff66, + 0xfe16, + 0xfcec, + 0xfc4f, + 0xfc9c, + 0xfe16, + 0x00c9, + 0x0485, + 0x08e0, + 0x0d43, + 0x1104, + 0x138c, + 0x1471, + 0x138c, + 0x1104, + 0x0d43, + 0x08e0, + 0x0485, + 0x00c9, + 0xfe16, + 0xfc9c, + 0xfc4f, + 0xfcec, + 0xfe16, + 0xff66, + 0x0086, + 0x0141, + 0x0182, + 0x0159, + 0x00ea, + 0x0060, + 0xffe4, + 0xff91, + 0xff6f, + 0xff7a, + 0xffa1, + 0xffd3, + 0x0000, + 0x001e, + 0x002c, + 0x002b, + 0x0020, + 0x0012, + 0x0003, + 0xfff6, +}; +int filter_sap_25k[] = { + 0x0019, + 0x0010, + 0x0000, + 0xffeb, + 0xffd7, + 0xffcf, + 0xffdb, + 0x0000, + 0x0037, + 0x006b, + 0x0080, + 0x005e, + 0x0000, + 0xff7d, + 0xff08, + 0xfedf, + 0xff31, + 0x0000, + 0x0114, + 0x0202, + 0x0250, + 0x01a6, + 0x0000, + 0xfdc9, + 0xfbcf, + 0xfb0b, + 0xfc51, + 0x0000, + 0x05c7, + 0x0ca9, + 0x1334, + 0x17e5, + 0x1999, + 0x17e5, + 0x1334, + 0x0ca9, + 0x05c7, + 0x0000, + 0xfc51, + 0xfb0b, + 0xfbcf, + 0xfdc9, + 0x0000, + 0x01a6, + 0x0250, + 0x0202, + 0x0114, + 0x0000, + 0xff31, + 0xfedf, + 0xff08, + 0xff7d, + 0x0000, + 0x005e, + 0x0080, + 0x006b, + 0x0037, + 0x0000, + 0xffdb, + 0xffcf, + 0xffd7, + 0xffeb, + 0x0000, + 0x0010, + 0x0019, +}; +int filter_sap_30k[] = { + 0xffea, + 0xffe5, + 0xffee, + 0x0005, + 0x0021, + 0x0034, + 0x002b, + 0x0000, + 0xffc0, + 0xff8f, + 0xff98, + 0xffec, + 0x0070, + 0x00dc, + 0x00dd, + 0x004c, + 0xff56, + 0xfe7c, + 0xfe57, + 0xff39, + 0x00e5, + 0x028a, + 0x0316, + 0x01d1, + 0xfee7, + 0xfb97, + 0xf9d6, + 0xfb77, + 0x013c, + 0x0a46, + 0x142f, + 0x1be0, + 0x1ec5, + 0x1be0, + 0x142f, + 0x0a46, + 0x013c, + 0xfb77, + 0xf9d6, + 0xfb97, + 0xfee7, + 0x01d1, + 0x0316, + 0x028a, + 0x00e5, + 0xff39, + 0xfe57, + 0xfe7c, + 0xff56, + 0x004c, + 0x00dd, + 0x00dc, + 0x0070, + 0xffec, + 0xff98, + 0xff8f, + 0xffc0, + 0x0000, + 0x002b, + 0x0034, + 0x0021, + 0x0005, + 0xffee, + 0xffe5, + 0xffea, +}; +int filter_sap_35k[] = { + 0x0003, + 0x0017, + 0x001d, + 0x000d, + 0xffeb, + 0xffcd, + 0xffcf, + 0x0000, + 0x0048, + 0x006e, + 0x0041, + 0xffc5, + 0xff4c, + 0xff44, + 0xffdf, + 0x00d0, + 0x015f, + 0x00ef, + 0xff8c, + 0xfe18, + 0xfdce, + 0xff4e, + 0x01e7, + 0x03c1, + 0x0303, + 0xff59, + 0xfab8, + 0xf8af, + 0xfc63, + 0x0667, + 0x13cd, + 0x1f46, + 0x23c8, + 0x1f46, + 0x13cd, + 0x0667, + 0xfc63, + 0xf8af, + 0xfab8, + 0xff59, + 0x0303, + 0x03c1, + 0x01e7, + 0xff4e, + 0xfdce, + 0xfe18, + 0xff8c, + 0x00ef, + 0x015f, + 0x00d0, + 0xffdf, + 0xff44, + 0xff4c, + 0xffc5, + 0x0041, + 0x006e, + 0x0048, + 0x0000, + 0xffcf, + 0xffcd, + 0xffeb, + 0x000d, + 0x001d, + 0x0017, + 0x0003, +}; +int filter_sap_40k[] = { + 0x0012, + 0xfff9, + 0xffe3, + 0xffe4, + 0x0005, + 0x002f, + 0x0035, + 0x0000, + 0xffb1, + 0xff9a, + 0xffef, + 0x007c, + 0x00b5, + 0x0038, + 0xff4d, + 0xfed6, + 0xff7e, + 0x00ef, + 0x01d4, + 0x0104, + 0xfed4, + 0xfd33, + 0xfe18, + 0x0163, + 0x0455, + 0x0392, + 0xfe71, + 0xf8ab, + 0xf86c, + 0x01ab, + 0x1247, + 0x2257, + 0x28fb, + 0x2257, + 0x1247, + 0x01ab, + 0xf86c, + 0xf8ab, + 0xfe71, + 0x0392, + 0x0455, + 0x0163, + 0xfe18, + 0xfd33, + 0xfed4, + 0x0104, + 0x01d4, + 0x00ef, + 0xff7e, + 0xfed6, + 0xff4d, + 0x0038, + 0x00b5, + 0x007c, + 0xffef, + 0xff9a, + 0xffb1, + 0x0000, + 0x0035, + 0x002f, + 0x0005, + 0xffe4, + 0xffe3, + 0xfff9, + 0x0012, +}; +int filter_sap_45k[] = { + 0xffe6, + 0xfff3, + 0x0012, + 0x0023, + 0x000b, + 0xffd8, + 0xffc7, + 0x0000, + 0x0055, + 0x0057, + 0xffde, + 0xff62, + 0xff90, + 0x006c, + 0x0105, + 0x0070, + 0xff0f, + 0xfe7d, + 0xffc5, + 0x01c9, + 0x020e, + 0xffa6, + 0xfcea, + 0xfd6c, + 0x01a0, + 0x0535, + 0x0305, + 0xfb77, + 0xf656, + 0xfcb0, + 0x0f92, + 0x24d1, + 0x2e1e, + 0x24d1, + 0x0f92, + 0xfcb0, + 0xf656, + 0xfb77, + 0x0305, + 0x0535, + 0x01a0, + 0xfd6c, + 0xfcea, + 0xffa6, + 0x020e, + 0x01c9, + 0xffc5, + 0xfe7d, + 0xff0f, + 0x0070, + 0x0105, + 0x006c, + 0xff90, + 0xff62, + 0xffde, + 0x0057, + 0x0055, + 0x0000, + 0xffc7, + 0xffd8, + 0x000b, + 0x0023, + 0x0012, + 0xfff3, + 0xffe6, +}; +int filter_sap_50k[] = { + 0x000f, + 0x001a, + 0x0000, + 0xffde, + 0xffe7, + 0x001e, + 0x003c, + 0x0000, + 0xffa7, + 0xffbe, + 0x004f, + 0x0098, + 0x0000, + 0xff2c, + 0xff67, + 0x00b2, + 0x014e, + 0x0000, + 0xfe42, + 0xfec3, + 0x016d, + 0x02aa, + 0x0000, + 0xfc6c, + 0xfd6a, + 0x030f, + 0x05f3, + 0x0000, + 0xf6aa, + 0xf82f, + 0x0bda, + 0x269d, + 0x3322, + 0x269d, + 0x0bda, + 0xf82f, + 0xf6aa, + 0x0000, + 0x05f3, + 0x030f, + 0xfd6a, + 0xfc6c, + 0x0000, + 0x02aa, + 0x016d, + 0xfec3, + 0xfe42, + 0x0000, + 0x014e, + 0x00b2, + 0xff67, + 0xff2c, + 0x0000, + 0x0098, + 0x004f, + 0xffbe, + 0xffa7, + 0x0000, + 0x003c, + 0x001e, + 0xffe7, + 0xffde, + 0x0000, + 0x001a, + 0x000f, +}; +int filter_sap_55k[] = { + 0x0006, + 0xffe7, + 0xffee, + 0x0019, + 0x0024, + 0xffed, + 0xffc2, + 0x0000, + 0x005c, + 0x0029, + 0xff8e, + 0xff92, + 0x0070, + 0x00ca, + 0xffbf, + 0xfed1, + 0xffd4, + 0x0183, + 0x00e2, + 0xfe5f, + 0xfe20, + 0x015a, + 0x0316, + 0xff87, + 0xfb99, + 0xfeb4, + 0x05ac, + 0x0488, + 0xf944, + 0xf4c1, + 0x0770, + 0x27f6, + 0x385c, + 0x27f6, + 0x0770, + 0xf4c1, + 0xf944, + 0x0488, + 0x05ac, + 0xfeb4, + 0xfb99, + 0xff87, + 0x0316, + 0x015a, + 0xfe20, + 0xfe5f, + 0x00e2, + 0x0183, + 0xffd4, + 0xfed1, + 0xffbf, + 0x00ca, + 0x0070, + 0xff92, + 0xff8e, + 0x0029, + 0x005c, + 0x0000, + 0xffc2, + 0xffed, + 0x0024, + 0x0019, + 0xffee, + 0xffe7, + 0x0006, +}; +int filter_sap_60k[] = { + 0xffe8, + 0x000a, + 0x001d, + 0xfff7, + 0xffd6, + 0x0007, + 0x003f, + 0x0000, + 0xffa3, + 0xfff2, + 0x0085, + 0x0028, + 0xff4b, + 0xffae, + 0x00ec, + 0x0092, + 0xfed7, + 0xff11, + 0x016a, + 0x0172, + 0xfe56, + 0xfdd7, + 0x01e8, + 0x032e, + 0xfde0, + 0xfb48, + 0x024f, + 0x0755, + 0xfd8e, + 0xf2eb, + 0x0288, + 0x2896, + 0x3d76, + 0x2896, + 0x0288, + 0xf2eb, + 0xfd8e, + 0x0755, + 0x024f, + 0xfb48, + 0xfde0, + 0x032e, + 0x01e8, + 0xfdd7, + 0xfe56, + 0x0172, + 0x016a, + 0xff11, + 0xfed7, + 0x0092, + 0x00ec, + 0xffae, + 0xff4b, + 0x0028, + 0x0085, + 0xfff2, + 0xffa3, + 0x0000, + 0x003f, + 0x0007, + 0xffd6, + 0xfff7, + 0x001d, + 0x000a, + 0xffe8, +}; +int iir_10k[] = { + 10, + 6, + 718, + -1687, + 14, + 27, + 14, +}; +int iir_12k[] = { + 10, + 6, + 669, + -1616, + 19, + 38, + 19, +}; +int iir_13k[] = { + 10, + 6, + 645, + -1581, + 22, + 44, + 22, +}; +int iir_14k[] = { + 10, + 6, + 623, + -1546, + 25, + 50, + 25, +}; +int iir_15k[] = { + 10, + 6, + 601, + -1511, + 29, + 57, + 29, +}; +int iir_16k[] = { + 10, + 6, + 580, + -1476, + 32, + 64, + 32, +}; +int iir_18k[] = { + 10, + 6, + 540, + -1407, + 39, + 79, + 39, +}; +int iir_20k[] = { + 10, + 6, + 504, + -1339, + 47, + 94, + 47, +}; +int filter_bb_10k[] = { + 0x0046, + 0x00be, + 0x021d, + 0x04bc, + 0x087c, + 0x0cb5, + 0x1065, + 0x128d, + 0x128d, + 0x1065, + 0x0cb5, + 0x087c, + 0x04bc, + 0x021d, + 0x00be, + 0x0046, +}; +int filter_bb_20k[] = { + 0xffa9, + 0xffc5, + 0x006f, + 0x02ad, + 0x070d, + 0x0d03, + 0x12df, + 0x1686, + 0x1686, + 0x12df, + 0x0d03, + 0x070d, + 0x02ad, + 0x006f, + 0xffc5, + 0xffa9, +}; +int iir_lpr_0[] = { + 10, + 6, + 453, + -1359, + 36, + 69, + 33, +}; +int iir_lpr_1[] = { + 10, + 6, + 494, + -1397, + 35, + 68, + 33, +}; +int iir_lpr_2[] = { + 10, + 6, + 580, + -1476, + 33, + 66, + 33, +}; +int iir_lpr_3[] = { + 10, + 6, + 715, + -1600, + 31, + 64, + 33, +}; +int iir_lpr_4[] = { + 10, + 6, + 906, + -1776, + 30, + 63, + 33, +}; +int iir_sap_0[] = { + 10, + 6, + 574, + -1532, + 20, + 38, + 18, +}; +int iir_sap_1[] = { + 10, + 6, + 609, + -1565, + 19, + 37, + 18, +}; +int iir_sap_2[] = { + 10, + 6, + 680, + -1634, + 18, + 36, + 18, +}; +int iir_sap_3[] = { + 10, + 6, + 789, + -1738, + 17, + 35, + 18, +}; +int iir_sap_4[] = { + 10, + 6, + 937, + -1879, + 16, + 34, + 18, +}; +int iir_sap_10k_0[] = { + 10, + 6, + 611, + -1580, + 16, + 31, + 15, +}; +int iir_sap_10k_1[] = { + 10, + 6, + 644, + -1612, + 16, + 30, + 15, +}; +int iir_sap_10k_2[] = { + 10, + 6, + 710, + -1676, + 15, + 29, + 15, +}; +int iir_sap_10k_3[] = { + 10, + 6, + 811, + -1774, + 14, + 29, + 15, +}; +int iir_sap_10k_4[] = { + 10, + 6, + 945, + -1904, + 13, + 28, + 15, +}; +int iir_sap_11k_0[] = { + 10, + 6, + 580, + -1540, + 19, + 37, + 17, +}; +int iir_sap_11k_1[] = { + 10, + 6, + 615, + -1573, + 19, + 36, + 17, +}; +int iir_sap_11k_2[] = { + 10, + 6, + 685, + -1641, + 17, + 35, + 17, +}; +int iir_sap_11k_3[] = { + 10, + 6, + 793, + -1744, + 16, + 34, + 17, +}; +int iir_sap_11k_4[] = { + 10, + 6, + 938, + -1883, + 16, + 33, + 17, +}; +int iir_sap_12k_0[] = { + 10, + 6, + 551, + -1500, + 22, + 43, + 20, +}; +int iir_sap_12k_1[] = { + 10, + 6, + 587, + -1535, + 22, + 42, + 20, +}; +int iir_sap_12k_2[] = { + 10, + 6, + 661, + -1606, + 20, + 41, + 20, +}; +int iir_sap_12k_3[] = { + 10, + 6, + 775, + -1714, + 19, + 40, + 20, +}; +int iir_sap_12k_4[] = { + 10, + 6, + 931, + -1862, + 19, + 39, + 20, +}; +int iir_sap_13k_0[] = { + 10, + 6, + 523, + -1461, + 26, + 49, + 24, +}; +int iir_sap_13k_1[] = { + 10, + 6, + 561, + -1497, + 25, + 48, + 24, +}; +int iir_sap_13k_2[] = { + 10, + 6, + 638, + -1570, + 24, + 47, + 24, +}; +int iir_sap_13k_3[] = { + 10, + 6, + 759, + -1684, + 22, + 46, + 24, +}; +int iir_sap_13k_4[] = { + 10, + 6, + 924, + -1840, + 21, + 45, + 24, +}; +int iir_sap_14k_0[] = { + 10, + 6, + 496, + -1423, + 30, + 56, + 27, +}; +int iir_sap_14k_1[] = { + 10, + 6, + 535, + -1460, + 28, + 55, + 27, +}; +int iir_sap_14k_2[] = { + 10, + 6, + 616, + -1535, + 27, + 54, + 27, +}; +int iir_sap_14k_3[] = { + 10, + 6, + 742, + -1653, + 25, + 52, + 27, +}; +int iir_sap_14k_4[] = { + 10, + 6, + 917, + -1817, + 24, + 51, + 27, +}; +int iir_sap_15k_0[] = { + 10, + 6, + 470, + -1385, + 33, + 64, + 30, +}; +int iir_sap_15k_1[] = { + 10, + 6, + 511, + -1423, + 32, + 62, + 30, +}; +int iir_sap_15k_2[] = { + 10, + 6, + 595, + -1500, + 30, + 61, + 30, +}; +int iir_sap_15k_3[] = { + 10, + 6, + 726, + -1622, + 29, + 59, + 30, +}; +int iir_sap_15k_4[] = { + 10, + 6, + 910, + -1793, + 28, + 58, + 30, +}; +int iir_sap_16k_0[] = { + 10, + 6, + 446, + -1348, + 37, + 71, + 34, +}; +int iir_sap_16k_1[] = { + 10, + 6, + 488, + -1386, + 36, + 70, + 34, +}; +int iir_sap_16k_2[] = { + 10, + 6, + 574, + -1466, + 34, + 68, + 34, +}; +int iir_sap_16k_3[] = { + 10, + 6, + 710, + -1591, + 32, + 66, + 34, +}; +int iir_sap_16k_4[] = { + 10, + 6, + 904, + -1768, + 31, + 65, + 34, +}; +int iir_sap_17k_0[] = { + 10, + 6, + 422, + -1312, + 42, + 79, + 38, +}; +int iir_sap_17k_1[] = { + 10, + 6, + 465, + -1351, + 40, + 78, + 38, +}; +int iir_sap_17k_2[] = { + 10, + 6, + 554, + -1431, + 38, + 75, + 38, +}; +int iir_sap_17k_3[] = { + 10, + 6, + 695, + -1559, + 36, + 73, + 38, +}; +int iir_sap_17k_4[] = { + 10, + 6, + 897, + -1743, + 34, + 72, + 38, +}; +int iir_sap_11_2k_0[] = { + 10, + 6, + 583, + -1544, + 19, + 36, + 17, +}; +int iir_sap_11_2k_1[] = { + 10, + 6, + 618, + -1577, + 18, + 35, + 17, +}; +int iir_sap_11_2k_2[] = { + 10, + 6, + 688, + -1644, + 17, + 34, + 17, +}; +int iir_sap_11_2k_3[] = { + 10, + 6, + 795, + -1747, + 16, + 33, + 17, +}; +int iir_sap_11_2k_4[] = { + 10, + 6, + 939, + -1885, + 16, + 33, + 17, +}; +int iir_sap_11_4k_0[] = { + 10, + 6, + 577, + -1536, + 20, + 37, + 18, +}; +int iir_sap_11_4k_1[] = { + 10, + 6, + 612, + -1569, + 19, + 36, + 18, +}; +int iir_sap_11_4k_2[] = { + 10, + 6, + 683, + -1637, + 18, + 35, + 18, +}; +int iir_sap_11_4k_3[] = { + 10, + 6, + 791, + -1741, + 17, + 34, + 18, +}; +int iir_sap_11_4k_4[] = { + 10, + 6, + 937, + -1881, + 16, + 34, + 18, +}; +int iir_sap_11_6k_0[] = { + 10, + 6, + 571, + -1528, + 20, + 38, + 18, +}; +int iir_sap_11_6k_1[] = { + 10, + 6, + 606, + -1562, + 19, + 38, + 18, +}; +int iir_sap_11_6k_2[] = { + 10, + 6, + 678, + -1630, + 18, + 37, + 18, +}; +int iir_sap_11_6k_3[] = { + 10, + 6, + 788, + -1735, + 17, + 36, + 18, +}; +int iir_sap_11_6k_4[] = { + 10, + 6, + 936, + -1877, + 17, + 35, + 18, +}; +int iir_sap_11_8k_0[] = { + 10, + 6, + 565, + -1520, + 21, + 40, + 19, +}; +int iir_sap_11_8k_1[] = { + 10, + 6, + 601, + -1554, + 20, + 39, + 19, +}; +int iir_sap_11_8k_2[] = { + 10, + 6, + 673, + -1623, + 19, + 38, + 19, +}; +int iir_sap_11_8k_3[] = { + 10, + 6, + 784, + -1729, + 18, + 37, + 19, +}; +int iir_sap_11_8k_4[] = { + 10, + 6, + 934, + -1873, + 17, + 36, + 19, +}; +int iir_sap_12_0k_0[] = { + 10, + 6, + 559, + -1512, + 21, + 41, + 19, +}; +int iir_sap_12_0k_1[] = { + 10, + 6, + 595, + -1546, + 21, + 40, + 19, +}; +int iir_sap_12_0k_2[] = { + 10, + 6, + 669, + -1616, + 19, + 39, + 19, +}; +int iir_sap_12_0k_3[] = { + 10, + 6, + 781, + -1723, + 18, + 38, + 19, +}; +int iir_sap_12_0k_4[] = { + 10, + 6, + 933, + -1869, + 18, + 37, + 19, +}; +int iir_sap_12_2k_0[] = { + 10, + 6, + 554, + -1504, + 22, + 42, + 20, +}; +int iir_sap_12_2k_1[] = { + 10, + 6, + 590, + -1539, + 21, + 41, + 20, +}; +int iir_sap_12_2k_2[] = { + 10, + 6, + 664, + -1609, + 20, + 40, + 20, +}; +int iir_sap_12_2k_3[] = { + 10, + 6, + 777, + -1717, + 19, + 39, + 20, +}; +int iir_sap_12_2k_4[] = { + 10, + 6, + 932, + -1864, + 18, + 38, + 20, +}; +int iir_sap_12_4k_0[] = { + 10, + 6, + 548, + -1496, + 23, + 43, + 21, +}; +int iir_sap_12_4k_1[] = { + 10, + 6, + 585, + -1531, + 22, + 43, + 21, +}; +int iir_sap_12_4k_2[] = { + 10, + 6, + 659, + -1602, + 21, + 41, + 21, +}; +int iir_sap_12_4k_3[] = { + 10, + 6, + 774, + -1711, + 19, + 40, + 21, +}; +int iir_sap_12_4k_4[] = { + 10, + 6, + 930, + -1860, + 19, + 39, + 21, +}; +int iir_sap_12_6k_0[] = { + 10, + 6, + 542, + -1488, + 23, + 45, + 21, +}; +int iir_sap_12_6k_1[] = { + 10, + 6, + 579, + -1523, + 23, + 44, + 21, +}; +int iir_sap_12_6k_2[] = { + 10, + 6, + 654, + -1595, + 21, + 43, + 21, +}; +int iir_sap_12_6k_3[] = { + 10, + 6, + 770, + -1705, + 20, + 41, + 21, +}; +int iir_sap_12_6k_4[] = { + 10, + 6, + 929, + -1856, + 19, + 41, + 21, +}; +int iir_sap_12_8k_0[] = { + 10, + 6, + 537, + -1481, + 24, + 46, + 22, +}; +int iir_sap_12_8k_1[] = { + 10, + 6, + 574, + -1516, + 23, + 45, + 22, +}; +int iir_sap_12_8k_2[] = { + 10, + 6, + 650, + -1588, + 22, + 44, + 22, +}; +int iir_sap_12_8k_3[] = { + 10, + 6, + 767, + -1699, + 21, + 43, + 22, +}; +int iir_sap_12_8k_4[] = { + 10, + 6, + 927, + -1851, + 20, + 42, + 22, +}; +int iir_sap_13_0k_0[] = { + 10, + 6, + 531, + -1473, + 25, + 47, + 23, +}; +int iir_sap_13_0k_1[] = { + 10, + 6, + 569, + -1508, + 24, + 46, + 23, +}; +int iir_sap_13_0k_2[] = { + 10, + 6, + 645, + -1581, + 23, + 45, + 23, +}; +int iir_sap_13_0k_3[] = { + 10, + 6, + 764, + -1693, + 21, + 44, + 23, +}; +int iir_sap_13_0k_4[] = { + 10, + 6, + 926, + -1847, + 20, + 43, + 23, +}; +int iir_sap_13_2k_0[] = { + 10, + 6, + 526, + -1465, + 26, + 49, + 23, +}; +int iir_sap_13_2k_1[] = { + 10, + 6, + 563, + -1501, + 25, + 48, + 23, +}; +int iir_sap_13_2k_2[] = { + 10, + 6, + 641, + -1574, + 23, + 46, + 23, +}; +int iir_sap_13_2k_3[] = { + 10, + 6, + 760, + -1687, + 22, + 45, + 23, +}; +int iir_sap_13_2k_4[] = { + 10, + 6, + 925, + -1842, + 21, + 44, + 23, +}; +int iir_sap_13_4k_0[] = { + 10, + 6, + 520, + -1457, + 26, + 50, + 24, +}; +int iir_sap_13_4k_1[] = { + 10, + 6, + 558, + -1493, + 25, + 49, + 24, +}; +int iir_sap_13_4k_2[] = { + 10, + 6, + 636, + -1567, + 24, + 48, + 24, +}; +int iir_sap_13_4k_3[] = { + 10, + 6, + 757, + -1681, + 22, + 46, + 24, +}; +int iir_sap_13_4k_4[] = { + 10, + 6, + 923, + -1838, + 22, + 45, + 24, +}; +int filter_sap_12k_1[] = { + 0xffe4, + 0xffe6, + 0xffec, + 0xfff5, + 0x0002, + 0x0013, + 0x002a, + 0x0046, + 0x0067, + 0x008e, + 0x00ba, + 0x00ec, + 0x0124, + 0x0160, + 0x01a2, + 0x01e7, + 0x0230, + 0x027c, + 0x02ca, + 0x0318, + 0x0367, + 0x03b5, + 0x0400, + 0x0448, + 0x048d, + 0x04cb, + 0x0504, + 0x0535, + 0x055f, + 0x0580, + 0x0598, + 0x05a6, + 0x05ab, + 0x05a6, + 0x0598, + 0x0580, + 0x055f, + 0x0535, + 0x0504, + 0x04cb, + 0x048d, + 0x0448, + 0x0400, + 0x03b5, + 0x0367, + 0x0318, + 0x02ca, + 0x027c, + 0x0230, + 0x01e7, + 0x01a2, + 0x0160, + 0x0124, + 0x00ec, + 0x00ba, + 0x008e, + 0x0067, + 0x0046, + 0x002a, + 0x0013, + 0x0002, + 0xfff5, + 0xffec, + 0xffe6, + 0xffe4, +}; + + +int filter_sap_12k_2[] = { + 0x0019, + 0x0038, + 0x0062, + 0x0093, + 0x00c8, + 0x00fb, + 0x0127, + 0x0143, + 0x0149, + 0x0133, + 0x00fe, + 0x00a8, + 0x0035, + 0xffaa, + 0xff13, + 0xfe7c, + 0xfdf6, + 0xfd93, + 0xfd63, + 0xfd76, + 0xfdd6, + 0xfe8c, + 0xff97, + 0x00f0, + 0x028b, + 0x0454, + 0x0632, + 0x080b, + 0x09c0, + 0x0b36, + 0x0c55, + 0x0d09, + 0x0d46, + 0x0d09, + 0x0c55, + 0x0b36, + 0x09c0, + 0x080b, + 0x0632, + 0x0454, + 0x028b, + 0x00f0, + 0xff97, + 0xfe8c, + 0xfdd6, + 0xfd76, + 0xfd63, + 0xfd93, + 0xfdf6, + 0xfe7c, + 0xff13, + 0xffaa, + 0x0035, + 0x00a8, + 0x00fe, + 0x0133, + 0x0149, + 0x0143, + 0x0127, + 0x00fb, + 0x00c8, + 0x0093, + 0x0062, + 0x0038, + 0x0019, +}; + + +int filter_sap_12k_4[] = { + 0x0018, + 0x002d, + 0x0037, + 0x0026, + 0xfff7, + 0xffb5, + 0xff7d, + 0xff71, + 0xffa6, + 0x0019, + 0x00a0, + 0x00fe, + 0x00f6, + 0x0070, + 0xff90, + 0xfeaf, + 0xfe3f, + 0xfe97, + 0xffbc, + 0x014f, + 0x029f, + 0x02f0, + 0x01d4, + 0xff71, + 0xfc97, + 0xfa93, + 0xfab8, + 0xfddf, + 0x03f6, + 0x0be8, + 0x13d7, + 0x19b0, + 0x1bd7, + 0x19b0, + 0x13d7, + 0x0be8, + 0x03f6, + 0xfddf, + 0xfab8, + 0xfa93, + 0xfc97, + 0xff71, + 0x01d4, + 0x02f0, + 0x029f, + 0x014f, + 0xffbc, + 0xfe97, + 0xfe3f, + 0xfeaf, + 0xff90, + 0x0070, + 0x00f6, + 0x00fe, + 0x00a0, + 0x0019, + 0xffa6, + 0xff71, + 0xff7d, + 0xffb5, + 0xfff7, + 0x0026, + 0x0037, + 0x002d, + 0x0018, +}; + +int filter_sap_15k_2[] = { + 0xffc6, + 0xff9a, + 0xff6b, + 0xff42, + 0xff2a, + 0xff2b, + 0xff4c, + 0xff90, + 0xfff2, + 0x006a, + 0x00e7, + 0x0155, + 0x019f, + 0x01b2, + 0x0181, + 0x0107, + 0x004b, + 0xff60, + 0xfe66, + 0xfd82, + 0xfce0, + 0xfcaa, + 0xfd01, + 0xfdf8, + 0xff95, + 0x01c5, + 0x0465, + 0x0740, + 0x0a17, + 0x0ca8, + 0x0eb2, + 0x1002, + 0x1076, + 0x1002, + 0x0eb2, + 0x0ca8, + 0x0a17, + 0x0740, + 0x0465, + 0x01c5, + 0xff95, + 0xfdf8, + 0xfd01, + 0xfcaa, + 0xfce0, + 0xfd82, + 0xfe66, + 0xff60, + 0x004b, + 0x0107, + 0x0181, + 0x01b2, + 0x019f, + 0x0155, + 0x00e7, + 0x006a, + 0xfff2, + 0xff90, + 0xff4c, + 0xff2b, + 0xff2a, + 0xff42, + 0xff6b, + 0xff9a, + 0xffc6, +}; + + + +int filter_sap_15k_4[] = { + 0xfff9, + 0xffdc, + 0xffb4, + 0xff9b, + 0xffae, + 0xfff8, + 0x005d, + 0x00a2, + 0x008d, + 0x000f, + 0xff65, + 0xfefb, + 0xff30, + 0x0006, + 0x010e, + 0x0196, + 0x0119, + 0xffb2, + 0xfe2a, + 0xfd96, + 0xfea1, + 0x00f5, + 0x0339, + 0x03be, + 0x0199, + 0xfd7e, + 0xf9c2, + 0xf959, + 0xfe40, + 0x0826, + 0x142f, + 0x1e04, + 0x21ce, + 0x1e04, + 0x142f, + 0x0826, + 0xfe40, + 0xf959, + 0xf9c2, + 0xfd7e, + 0x0199, + 0x03be, + 0x0339, + 0x00f5, + 0xfea1, + 0xfd96, + 0xfe2a, + 0xffb2, + 0x0119, + 0x0196, + 0x010e, + 0x0006, + 0xff30, + 0xfefb, + 0xff65, + 0x000f, + 0x008d, + 0x00a2, + 0x005d, + 0xfff8, + 0xffae, + 0xff9b, + 0xffb4, + 0xffdc, + 0xfff9, +}; diff --git a/drivers/amlogic/atv_demod/aud_demod_settings.h b/drivers/amlogic/atv_demod/aud_demod_settings.h new file mode 100644 index 000000000000..de80ab543360 --- /dev/null +++ b/drivers/amlogic/atv_demod/aud_demod_settings.h @@ -0,0 +1,168 @@ +#ifndef _Aud_Demod_Settings_h_ +#define _Aud_Demod_Settings_h_ + +extern int M_DTO; +extern int A2K_DTO; +extern int BG_DTO; +extern int A2G_DTO; +extern int EIAJ_DTO; +extern int SAP_DTO; +extern int A2K_INDICATOR_DTO; +extern int A2K_STEREO_DTO; +extern int A2K_DUAL_DTO; +extern int A2G_INDICATOR_DTO; +extern int A2G_STEREO_DTO; +extern int A2G_DUAL_DTO; +extern int filter_25k[]; +extern int filter_50k[]; +extern int filter_75k[]; +extern int filter_100k[]; +extern int filter_125k[]; +extern int filter_150k[]; +extern int filter_200k[]; +extern int filter_300k[]; +extern int filter_400k[]; +extern int filter_550k[]; +extern int filter_sap_10k[]; +extern int filter_sap_15k[]; +extern int filter_sap_20k[]; +extern int filter_sap_25k[]; +extern int filter_sap_30k[]; +extern int filter_sap_35k[]; +extern int filter_sap_40k[]; +extern int filter_sap_45k[]; +extern int filter_sap_50k[]; +extern int filter_sap_55k[]; +extern int filter_sap_60k[]; +extern int filter_bb_10k[]; +extern int filter_bb_20k[]; +extern int iir_10k[]; +extern int iir_12k[]; +extern int iir_13k[]; +extern int iir_14k[]; +extern int iir_15k[]; +extern int iir_16k[]; +extern int iir_18k[]; +extern int iir_20k[]; +extern int iir_lpr_0[]; +extern int iir_lpr_1[]; +extern int iir_lpr_2[]; +extern int iir_lpr_3[]; +extern int iir_lpr_4[]; +extern int iir_sap_0[]; +extern int iir_sap_1[]; +extern int iir_sap_2[]; +extern int iir_sap_3[]; +extern int iir_sap_4[]; +extern int iir_sap_0[]; +extern int iir_sap_1[]; +extern int iir_sap_2[]; +extern int iir_sap_3[]; +extern int iir_sap_4[]; +extern int iir_sap_10k_0[]; +extern int iir_sap_10k_1[]; +extern int iir_sap_10k_2[]; +extern int iir_sap_10k_3[]; +extern int iir_sap_10k_4[]; +extern int iir_sap_11k_0[]; +extern int iir_sap_11k_1[]; +extern int iir_sap_11k_2[]; +extern int iir_sap_11k_3[]; +extern int iir_sap_11k_4[]; +extern int iir_sap_12k_0[]; +extern int iir_sap_12k_1[]; +extern int iir_sap_12k_2[]; +extern int iir_sap_12k_3[]; +extern int iir_sap_12k_4[]; +extern int iir_sap_13k_0[]; +extern int iir_sap_13k_1[]; +extern int iir_sap_13k_2[]; +extern int iir_sap_13k_3[]; +extern int iir_sap_13k_4[]; +extern int iir_sap_14k_0[]; +extern int iir_sap_14k_1[]; +extern int iir_sap_14k_2[]; +extern int iir_sap_14k_3[]; +extern int iir_sap_14k_4[]; +extern int iir_sap_15k_0[]; +extern int iir_sap_15k_1[]; +extern int iir_sap_15k_2[]; +extern int iir_sap_15k_3[]; +extern int iir_sap_15k_4[]; +extern int iir_sap_16k_0[]; +extern int iir_sap_16k_1[]; +extern int iir_sap_16k_2[]; +extern int iir_sap_16k_3[]; +extern int iir_sap_16k_4[]; +extern int iir_sap_17k_0[]; +extern int iir_sap_17k_1[]; +extern int iir_sap_17k_2[]; +extern int iir_sap_17k_3[]; +extern int iir_sap_17k_4[]; +extern int iir_sap_11_2k_0[]; +extern int iir_sap_11_2k_1[]; +extern int iir_sap_11_2k_2[]; +extern int iir_sap_11_2k_3[]; +extern int iir_sap_11_2k_4[]; +extern int iir_sap_11_4k_0[]; +extern int iir_sap_11_4k_1[]; +extern int iir_sap_11_4k_2[]; +extern int iir_sap_11_4k_3[]; +extern int iir_sap_11_4k_4[]; +extern int iir_sap_11_6k_0[]; +extern int iir_sap_11_6k_1[]; +extern int iir_sap_11_6k_2[]; +extern int iir_sap_11_6k_3[]; +extern int iir_sap_11_6k_4[]; +extern int iir_sap_11_8k_0[]; +extern int iir_sap_11_8k_1[]; +extern int iir_sap_11_8k_2[]; +extern int iir_sap_11_8k_3[]; +extern int iir_sap_11_8k_4[]; +extern int iir_sap_12_0k_0[]; +extern int iir_sap_12_0k_1[]; +extern int iir_sap_12_0k_2[]; +extern int iir_sap_12_0k_3[]; +extern int iir_sap_12_0k_4[]; +extern int iir_sap_12_2k_0[]; +extern int iir_sap_12_2k_1[]; +extern int iir_sap_12_2k_2[]; +extern int iir_sap_12_2k_3[]; +extern int iir_sap_12_2k_4[]; +extern int iir_sap_12_4k_0[]; +extern int iir_sap_12_4k_1[]; +extern int iir_sap_12_4k_2[]; +extern int iir_sap_12_4k_3[]; +extern int iir_sap_12_4k_4[]; +extern int iir_sap_12_6k_0[]; +extern int iir_sap_12_6k_1[]; +extern int iir_sap_12_6k_2[]; +extern int iir_sap_12_6k_3[]; +extern int iir_sap_12_6k_4[]; +extern int iir_sap_12_8k_0[]; +extern int iir_sap_12_8k_1[]; +extern int iir_sap_12_8k_2[]; +extern int iir_sap_12_8k_3[]; +extern int iir_sap_12_8k_4[]; +extern int iir_sap_13_0k_0[]; +extern int iir_sap_13_0k_1[]; +extern int iir_sap_13_0k_2[]; +extern int iir_sap_13_0k_3[]; +extern int iir_sap_13_0k_4[]; +extern int iir_sap_13_2k_0[]; +extern int iir_sap_13_2k_1[]; +extern int iir_sap_13_2k_2[]; +extern int iir_sap_13_2k_3[]; +extern int iir_sap_13_2k_4[]; +extern int iir_sap_13_4k_0[]; +extern int iir_sap_13_4k_1[]; +extern int iir_sap_13_4k_2[]; +extern int iir_sap_13_4k_3[]; +extern int iir_sap_13_4k_4[]; +extern int filter_sap_12k_1[]; +extern int filter_sap_12k_2[]; +extern int filter_sap_12k_4[]; + +extern int filter_sap_15k_2[]; +extern int filter_sap_15k_4[]; +#endif /* _Settings_h_ */ diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c index 3ba85d6bc0d1..c76803f8c1c9 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe.c @@ -118,7 +118,7 @@ unsigned int av1_plugin_state; unsigned int av2_plugin_state; #endif -#ifdef CONFIG_AM_DVB +#ifdef CONFIG_AMLOGIC_ATV_DEMOD static struct tvafe_info_s *g_tvafe_info; #endif @@ -200,7 +200,7 @@ void tvafe_cma_release(struct tvafe_dev_s *devp) } #endif -#ifdef CONFIG_AM_DVB +#ifdef CONFIG_AMLOGIC_ATV_DEMOD static int tvafe_get_v_fmt(void) { int fmt = 0; @@ -295,7 +295,7 @@ int tvafe_dec_open(struct tvin_frontend_s *fe, enum tvin_port_e port) /* set the flag to enabble ioctl access */ devp->flags |= TVAFE_FLAG_DEV_OPENED; tvafe_clk_status = true; -#ifdef CONFIG_AM_DVB +#ifdef CONFIG_AMLOGIC_ATV_DEMOD g_tvafe_info = tvafe; /* register aml_fe hook for atv search */ aml_fe_hook_cvd(tvafe_cvd2_get_atv_format, tvafe_cvd2_get_hv_lock, @@ -457,7 +457,7 @@ void tvafe_dec_close(struct tvin_frontend_s *fe) } tvafe_clk_status = false; /*del_timer_sync(&devp->timer);*/ -#ifdef CONFIG_AM_DVB +#ifdef CONFIG_AMLOGIC_ATV_DEMOD g_tvafe_info = NULL; /* register aml_fe hook for atv search */ aml_fe_hook_cvd(NULL, NULL, NULL); @@ -1147,7 +1147,7 @@ static int tvafe_drv_probe(struct platform_device *pdev) } s_tvafe_data = (struct meson_tvafe_data *)match->data; - tvafe_pr_info("%s£¬cpu_id:%d,name:%s\n", __func__, + tvafe_pr_info("%s:cpu_id:%d,name:%s\n", __func__, s_tvafe_data->cpu_id, s_tvafe_data->name); tvafe_clktree_probe(&pdev->dev); diff --git a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c index 3565b833347b..f4695e5a24c7 100644 --- a/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c +++ b/drivers/amlogic/media/vin/tvin/tvafe/tvafe_general.c @@ -811,6 +811,7 @@ int tvafe_adc_get_pll_flag(void) mutex_unlock(&pll_mutex); return ret; } +EXPORT_SYMBOL(tvafe_adc_get_pll_flag); /* * tvafe init the whole module diff --git a/include/linux/amlogic/aml_atvdemod.h b/include/linux/amlogic/aml_atvdemod.h new file mode 100644 index 000000000000..e08029e839a1 --- /dev/null +++ b/include/linux/amlogic/aml_atvdemod.h @@ -0,0 +1,19 @@ +/* + * amlogic atv demod driver + * + * Author: nengwen.chen + * + * + * Copyright (C) 2018 Amlogic Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __AML_ATVDEMOD_H__ +#define __AML_ATVDEMOD_H__ + +extern void aml_fe_get_atvaudio_state(int *state); + +#endif /* __AML_ATVDEMOD_H__ */ diff --git a/sound/soc/amlogic/meson/tv.c b/sound/soc/amlogic/meson/tv.c index 51ed2c013afa..03737a951e94 100644 --- a/sound/soc/amlogic/meson/tv.c +++ b/sound/soc/amlogic/meson/tv.c @@ -49,6 +49,9 @@ #ifdef CONFIG_AMLOGIC_MEDIA_TVIN_HDMI #include #endif +#ifdef CONFIG_AMLOGIC_ATV_DEMOD +#include +#endif #include "i2s.h" #include "audio_hw.h" @@ -650,7 +653,7 @@ static int aml_get_hdmiin_audio_format(struct snd_kcontrol *kcontrol, } #endif -#ifdef CONFIG_AM_DVB +#ifdef CONFIG_AMLOGIC_ATV_DEMOD static const char *const atv_audio_is_stable[] = { "false", "true" @@ -667,7 +670,7 @@ static int aml_get_atv_audio_stable(struct snd_kcontrol *kcontrol, ucontrol->value.integer.value[0] = state; return 0; } -#endif /* CONFIG_AM_DVB */ +#endif /* CONFIG_AMLOGIC_ATV_DEMOD */ #ifdef CONFIG_TVIN_VDIN static const char *const av_audio_is_stable[] = { "false", @@ -733,7 +736,7 @@ static const struct snd_kcontrol_new aml_tv_controls[] = { aml_get_atmos_audio_edid, aml_set_atmos_audio_edid), #endif -#ifdef CONFIG_AM_DVB +#ifdef CONFIG_AMLOGIC_ATV_DEMOD SOC_ENUM_EXT("ATV audio stable", atv_audio_status_enum, aml_get_atv_audio_stable, NULL),