blob: 02afac5c05f399c314973b8d791ab1bdc3603f31 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include "demod_func.h"
#include "amlfrontend.h"
#include "dvbt_func.h"
#include "aml_demod.h"
#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/delay.h>
/*#include "acf_filter_coefficient.h"*/
#include <linux/mutex.h>
#include <linux/amlogic/media/frame_provider/tvin/tvin.h>
MODULE_PARM_DESC(debug_demod, "\n\t\t Enable frontend debug information");
static int debug_demod;
module_param(debug_demod, int, 0644);
MODULE_PARM_DESC(demod_mobile_power, "\n\t\t demod_mobile_power debug information");
static int demod_mobile_power = 100;
module_param(demod_mobile_power, int, 0644);
/* protect register access */
static struct mutex mp;
static struct mutex dtvpll_init_lock;
static int dtvpll_init;
#if defined DEMOD_FPGA_VERSION
static int fpga_version = 1;
#else
static int fpga_version = -1;
#endif
void dtvpll_lock_init(void)
{
mutex_init(&dtvpll_init_lock);
}
void dtvpll_init_flag(int on)
{
mutex_lock(&dtvpll_init_lock);
dtvpll_init = on;
mutex_unlock(&dtvpll_init_lock);
pr_err("%s %d\n", __func__, on);
}
int get_dtvpll_init_flag(void)
{
int val;
/*mutex_lock(&dtvpll_init_lock);*/
val = dtvpll_init;
/*mutex_unlock(&dtvpll_init_lock);*/
if (!val)
pr_err("%s: %d\n", __func__, val);
return val;
}
void adc_dpll_setup(int clk_a, int clk_b, int clk_sys, struct aml_demod_sta *demod_sta)
{
int unit, found, ena, enb, div2;
int pll_m, pll_n, pll_od_a, pll_od_b, pll_xd_a, pll_xd_b;
long freq_osc, freq_dco, freq_b, freq_a, freq_sys;
long freq_b_act, freq_a_act, freq_sys_act, err_tmp, best_err;
union adc_pll_cntl adc_pll_cntl;
union adc_pll_cntl2 adc_pll_cntl2;
union adc_pll_cntl3 adc_pll_cntl3;
union adc_pll_cntl4 adc_pll_cntl4;
union demod_dig_clk dig_clk_cfg;
struct dfe_adcpll_para ddemod_pll;
int sts_pll = 0;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
dtvpll_init_flag(1);
return;
}
dig_clk_cfg.d32 = 0;
adc_pll_cntl.d32 = 0;
adc_pll_cntl2.d32 = 0;
adc_pll_cntl3.d32 = 0;
adc_pll_cntl4.d32 = 0;
dig_clk_cfg.d32 = 0;
PR_DBG("target clk_a %d clk_b %d\n", clk_a, clk_b);
unit = 10000; /* 10000 as 1 MHz, 0.1 kHz resolution. */
freq_osc = 24 * unit;
if (clk_a < 1000)
freq_a = clk_a * unit;
else
freq_a = clk_a * (unit / 1000);
if (clk_b < 1000)
freq_b = clk_b * unit;
else
freq_b = clk_b * (unit / 1000);
ena = clk_a > 0 ? 1 : 0;
enb = clk_b > 0 ? 1 : 0;
if (ena || enb)
adc_pll_cntl3.b.enable = 1;
adc_pll_cntl3.b.reset = 1;
found = 0;
best_err = 100 * unit;
pll_od_a = 1;
pll_od_b = 1;
pll_n = 1;
for (pll_m = 1; pll_m < 512; pll_m++) {
/* for (pll_n=1; pll_n<=5; pll_n++) { */
#if 0
if ((is_meson_txl_cpu()) || (is_meson_txlx_cpu())
|| (is_meson_gxlx_cpu()) || (is_meson_txhd_cpu())) {
freq_dco = freq_osc * pll_m / pll_n / 2;
/*txl add div2*/
if (freq_dco < 700 * unit || freq_dco > 1000 * unit)
continue;
} else {
freq_dco = freq_osc * pll_m / pll_n;
if (freq_dco < 750 * unit || freq_dco > 1550 * unit)
continue;
}
#else
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {
/*txl add div2*/
freq_dco = freq_osc * pll_m / pll_n / 2;
if (freq_dco < 700 * unit || freq_dco > 1000 * unit)
continue;
} else {
freq_dco = freq_osc * pll_m / pll_n;
if (freq_dco < 750 * unit || freq_dco > 1550 * unit)
continue;
}
#endif
pll_xd_a = freq_dco / (1 << pll_od_a) / freq_a;
pll_xd_b = freq_dco / (1 << pll_od_b) / freq_b;
freq_a_act = freq_dco / (1 << pll_od_a) / pll_xd_a;
freq_b_act = freq_dco / (1 << pll_od_b) / pll_xd_b;
err_tmp = (freq_a_act - freq_a) * ena + (freq_b_act - freq_b) *
enb;
if (err_tmp >= best_err)
continue;
adc_pll_cntl.b.pll_m = pll_m;
adc_pll_cntl.b.pll_n = pll_n;
adc_pll_cntl.b.pll_od0 = pll_od_b;
adc_pll_cntl.b.pll_od1 = pll_od_a;
adc_pll_cntl.b.pll_xd0 = pll_xd_b;
adc_pll_cntl.b.pll_xd1 = pll_xd_a;
#if 0
if ((is_meson_txl_cpu()) || (is_meson_txlx_cpu())
|| (is_meson_gxlx_cpu()) || (is_meson_txhd_cpu())) {
adc_pll_cntl4.b.pll_od3 = 0;
adc_pll_cntl.b.pll_od2 = 0;
} else {
adc_pll_cntl2.b.div2_ctrl =
freq_dco > 1000 * unit ? 1 : 0;
}
#else
/*if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL)) {
adc_pll_cntl4.b.pll_od3 = 0;
adc_pll_cntl.b.pll_od2 = 0;
} else {
adc_pll_cntl2.b.div2_ctrl =
freq_dco > 1000 * unit ? 1 : 0;
}
#endif
found = 1;
best_err = err_tmp;
/* } */
}
pll_m = adc_pll_cntl.b.pll_m;
pll_n = adc_pll_cntl.b.pll_n;
pll_od_b = adc_pll_cntl.b.pll_od0;
pll_od_a = adc_pll_cntl.b.pll_od1;
pll_xd_b = adc_pll_cntl.b.pll_xd0;
pll_xd_a = adc_pll_cntl.b.pll_xd1;
#if 0
if ((is_meson_txl_cpu()) || (is_meson_txlx_cpu())
|| (is_meson_gxlx_cpu()) || (is_meson_txhd_cpu()))
div2 = 1;
else
div2 = adc_pll_cntl2.b.div2_ctrl;
#else
/*if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL))*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL))
div2 = 1;
else
div2 = adc_pll_cntl2.b.div2_ctrl;
#endif
/*
* p_adc_pll_cntl = adc_pll_cntl.d32;
* p_adc_pll_cntl2 = adc_pll_cntl2.d32;
* p_adc_pll_cntl3 = adc_pll_cntl3.d32;
* p_adc_pll_cntl4 = adc_pll_cntl4.d32;
*/
adc_pll_cntl3.b.reset = 0;
/* *p_adc_pll_cntl3 = adc_pll_cntl3.d32; */
if (!found) {
PR_DBG(" ERROR can't setup %7ld kHz %7ld kHz\n",
freq_b / (unit / 1000), freq_a / (unit / 1000));
} else {
#if 0
if ((is_meson_txl_cpu()) || (is_meson_txlx_cpu())
|| (is_meson_gxlx_cpu()) || (is_meson_txhd_cpu()))
freq_dco = freq_osc * pll_m / pll_n / 2;
else
freq_dco = freq_osc * pll_m / pll_n;
#else
/*if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL))*/
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TXL))
freq_dco = freq_osc * pll_m / pll_n / 2;
else
freq_dco = freq_osc * pll_m / pll_n;
#endif
PR_DBG(" ADC PLL M %3d N %3d\n", pll_m, pll_n);
PR_DBG(" ADC PLL DCO %ld kHz\n", freq_dco / (unit / 1000));
PR_DBG(" ADC PLL XD %3d OD %3d\n", pll_xd_b, pll_od_b);
PR_DBG(" ADC PLL XD %3d OD %3d\n", pll_xd_a, pll_od_a);
freq_a_act = freq_dco / (1 << pll_od_a) / pll_xd_a;
freq_b_act = freq_dco / (1 << pll_od_b) / pll_xd_b;
PR_DBG(" B %7ld kHz %7ld kHz\n",
freq_b / (unit / 1000), freq_b_act / (unit / 1000));
PR_DBG(" A %7ld kHz %7ld kHz\n",
freq_a / (unit / 1000), freq_a_act / (unit / 1000));
if (clk_sys > 0) {
dig_clk_cfg.b.demod_clk_en = 1;
dig_clk_cfg.b.demod_clk_sel = 3;
if (clk_sys < 1000)
freq_sys = clk_sys * unit;
else
freq_sys = clk_sys * (unit / 1000);
dig_clk_cfg.b.demod_clk_div = freq_dco / (1 + div2) /
freq_sys - 1;
freq_sys_act = freq_dco / (1 + div2) /
(dig_clk_cfg.b.demod_clk_div + 1);
PR_DBG(" SYS %7ld kHz div %d+1 %7ld kHz\n",
freq_sys / (unit / 1000),
dig_clk_cfg.b.demod_clk_div,
freq_sys_act / (unit / 1000));
} else {
dig_clk_cfg.b.demod_clk_en = 0;
}
/* *p_demod_dig_clk = dig_clk_cfg.d32; */
}
ddemod_pll.adcpllctl = adc_pll_cntl.d32;
ddemod_pll.demodctl = dig_clk_cfg.d32;
ddemod_pll.atsc = 0;
switch (demod_sta->delsys) {
case SYS_ATSC:
case SYS_ATSCMH:
case SYS_DVBC_ANNEX_B:
ddemod_pll.atsc = 1;
break;
default:
break;
}
#ifdef CONFIG_AMLOGIC_MEDIA_ADC
sts_pll = adc_set_pll_cntl(1, ADC_DTV_DEMODPLL, &ddemod_pll);
#endif
if (sts_pll < 0) {
/*set pll fail*/
PR_ERR("%s:set pll fail! please check!\n", __func__);
} else {
dtvpll_init_flag(1);
}
}
void demod_set_adc_core_clk(int adc_clk, int sys_clk, struct aml_demod_sta *demod_sta)
{
adc_dpll_setup(25, adc_clk, sys_clk, demod_sta);
}
void demod_set_cbus_reg(unsigned int data, unsigned int addr)
{
void __iomem *vaddr;
PR_DBG("[cbus][write]%x\n", (IO_CBUS_PHY_BASE + (addr << 2)));
vaddr = ioremap((IO_CBUS_PHY_BASE + (addr << 2)), 0x4);
writel(data, vaddr);
iounmap(vaddr);
}
unsigned int demod_read_cbus_reg(unsigned int addr)
{
/* return __raw_readl(CBUS_REG_ADDR(addr)); */
unsigned int tmp;
void __iomem *vaddr;
vaddr = ioremap((IO_CBUS_PHY_BASE + (addr << 2)), 0x4);
tmp = readl(vaddr);
iounmap(vaddr);
/* tmp = aml_read_cbus(addr); */
PR_DBG("[cbus][read]%x,data is %x\n",
(IO_CBUS_PHY_BASE + (addr << 2)), tmp);
return tmp;
}
void demod_set_ao_reg(unsigned int data, unsigned int addr)
{
writel(data, gbase_aobus() + addr);
}
unsigned int demod_read_ao_reg(unsigned int addr)
{
unsigned int tmp;
tmp = readl(gbase_aobus() + addr);
return tmp;
}
void demod_set_demod_reg(unsigned int data, unsigned int addr)
{
void __iomem *vaddr;
mutex_lock(&mp);
vaddr = ioremap((addr), 0x4);
writel(data, vaddr);
iounmap(vaddr);
mutex_unlock(&mp);
}
void demod_set_tvfe_reg(unsigned int data, unsigned int addr)
{
void __iomem *vaddr;
mutex_lock(&mp);
/* printk("[demod][write]%x,data is %x\n",(addr),data);*/
vaddr = ioremap((addr), 0x4);
writel(data, vaddr);
iounmap(vaddr);
mutex_unlock(&mp);
}
unsigned int demod_read_demod_reg(unsigned int addr)
{
unsigned int tmp;
void __iomem *vaddr;
mutex_lock(&mp);
vaddr = ioremap((addr), 0x4);
tmp = readl(vaddr);
iounmap(vaddr);
mutex_unlock(&mp);
return tmp;
}
void power_sw_hiu_reg(int on)
{
if (on == PWR_ON) {
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
dd_hiu_reg_write(HHI_DEMOD_MEM_PD_REG, 0);
else
dd_hiu_reg_write(HHI_DEMOD_MEM_PD_REG,
(dd_hiu_reg_read(HHI_DEMOD_MEM_PD_REG)
& (~0x2fff)));
} else {
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
dd_hiu_reg_write(HHI_DEMOD_MEM_PD_REG,
0xffffffff);
else
dd_hiu_reg_write(HHI_DEMOD_MEM_PD_REG,
(dd_hiu_reg_read(HHI_DEMOD_MEM_PD_REG) | 0x2fff));
}
}
void power_sw_reset_reg(int en)
{
if (en) {
reset_reg_write(RESET_RESET0_LEVEL,
(reset_reg_read(RESET_RESET0_LEVEL) & (~(0x1 << 8))));
} else {
reset_reg_write(RESET_RESET0_LEVEL,
(reset_reg_read(RESET_RESET0_LEVEL) | (0x1 << 8)));
}
}
void demod_power_switch(int pwr_cntl)
{
int reg_data;
unsigned int pwr_slp_bit;
unsigned int pwr_iso_bit;
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!devp) {
pr_err("%s devp is NULL\n", __func__);
return;
}
/* DO NOT set any power related regs in T5 */
if (devp->data->hw_ver >= DTVDEMOD_HW_T5) {
if (devp->data->hw_ver >= DTVDEMOD_HW_T5D) {
/* UART pin mux for RISCV debug */
/* demod_set_ao_reg(0x104411, 0x14); */
}
return;
}
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2)) {
pwr_slp_bit = 23;
pwr_iso_bit = 23;
} else {
pwr_slp_bit = 10;
pwr_iso_bit = 14;
}
if (is_meson_gxlx_cpu()) {
PR_DBG("[PWR]: GXLX not support power switch,power mem\n");
power_sw_hiu_reg(PWR_ON);
} else if (pwr_cntl == PWR_ON) {
PR_DBG("[PWR]: Power on demod_comp %x,%x\n",
AO_RTI_GEN_PWR_SLEEP0, AO_RTI_GEN_PWR_ISO0);
/* Powerup demod_comb */
reg_data = demod_read_ao_reg(AO_RTI_GEN_PWR_SLEEP0);
demod_set_ao_reg((reg_data & (~(0x1 << pwr_slp_bit))),
AO_RTI_GEN_PWR_SLEEP0);
/* Power up memory */
power_sw_hiu_reg(PWR_ON);
/* reset */
power_sw_reset_reg(1);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2))
/* remove isolation */
demod_set_ao_reg(
(demod_read_ao_reg(AO_RTI_GEN_PWR_ISO0) &
(~(0x1 << pwr_iso_bit))),
AO_RTI_GEN_PWR_ISO0);
else
/* remove isolation */
demod_set_ao_reg(
(demod_read_ao_reg(AO_RTI_GEN_PWR_ISO0) &
(~(0x3 << pwr_iso_bit))),
AO_RTI_GEN_PWR_ISO0);
/* pull up reset */
power_sw_reset_reg(0);
} else {
PR_DBG("[PWR]: Power off demod_comp\n");
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TM2))
/* add isolation */
demod_set_ao_reg(
(demod_read_ao_reg(AO_RTI_GEN_PWR_ISO0) |
(0x1 << pwr_iso_bit)), AO_RTI_GEN_PWR_ISO0);
else
/* add isolation */
demod_set_ao_reg(
(demod_read_ao_reg(AO_RTI_GEN_PWR_ISO0) |
(0x3 << pwr_iso_bit)), AO_RTI_GEN_PWR_ISO0);
/* power down memory */
power_sw_hiu_reg(PWR_OFF);
/* power down demod_comb */
reg_data = demod_read_ao_reg(AO_RTI_GEN_PWR_SLEEP0);
demod_set_ao_reg((reg_data | (0x1 << pwr_slp_bit)),
AO_RTI_GEN_PWR_SLEEP0);
}
}
/* 0:DVBC/J.83B, 1:DVBT/ISDBT, 2:ATSC, 3:DTMB */
void demod_set_mode_ts(enum fe_delivery_system delsys)
{
union demod_cfg0 cfg0;
unsigned int dvbt_mode = 0x11;
cfg0.b.adc_format = 1;
cfg0.b.adc_regout = 1;
switch (delsys) {
case SYS_DTMB:
cfg0.b.ts_sel = 1;
cfg0.b.mode = 1;
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
cfg0.b.adc_format = 0;
cfg0.b.adc_regout = 0;
}
break;
case SYS_ISDBT:
cfg0.b.ts_sel = 1<<1;
cfg0.b.mode = 1<<1;
cfg0.b.adc_format = 0;
cfg0.b.adc_regout = 0;
break;
case SYS_ATSC:
case SYS_ATSCMH:
case SYS_DVBC_ANNEX_B:
cfg0.b.ts_sel = 1<<2;
cfg0.b.mode = 1<<2;
cfg0.b.adc_format = 0;
if (!cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
cfg0.b.adc_regout = 1;
cfg0.b.adc_regadj = 2;
}
break;
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
if (is_meson_gxtvbb_cpu() || is_meson_txl_cpu()) {
#ifndef CONFIG_AMLOGIC_REMOVE_OLD
cfg0.b.ts_sel = 2;
cfg0.b.mode = 7;
cfg0.b.adc_format = 1;
cfg0.b.adc_regout = 0;
#endif
} else {
cfg0.b.ts_sel = 1<<3;
cfg0.b.mode = 1<<3;
cfg0.b.adc_format = 0;
cfg0.b.adc_regout = 0;
}
break;
case SYS_DVBT:
case SYS_DVBT2:
dvbt_mode = 0x110011;
break;
case SYS_DVBS:
case SYS_DVBS2:
dvbt_mode = 0x220011;
break;
default:
break;
}
demod_top_write_reg(DEMOD_TOP_REG0, cfg0.d32);
demod_top_write_reg(DEMOD_TOP_REGC, dvbt_mode);
}
void clocks_set_sys_defaults(struct aml_dtvdemod *demod, unsigned int adc_clk)
{
union demod_cfg2 cfg2;
int sts_pll = 0;
#ifdef CONFIG_AMLOGIC_MEDIA_ADC
struct dfe_adcpll_para ddemod_pll;
#endif
demod_power_switch(PWR_ON);
#ifdef CONFIG_AMLOGIC_MEDIA_ADC
adc_set_ddemod_default(demod->demod_status.delsys);
#endif
demod_set_demod_default();
#ifdef CONFIG_AMLOGIC_MEDIA_ADC
ddemod_pll.delsys = demod->demod_status.delsys;
ddemod_pll.adc_clk = adc_clk;
sts_pll = adc_set_pll_cntl(1, ADC_DTV_DEMOD, &ddemod_pll);
#endif
if (sts_pll < 0) {
/*set pll fail*/
PR_ERR("%s:set pll default fail! please check!\n", __func__);
}
demod_set_mode_ts(demod->demod_status.delsys);
cfg2.b.biasgen_en = 1;
cfg2.b.en_adc = 1;
demod_top_write_reg(DEMOD_TOP_REG8, cfg2.d32);
PR_ERR("%s:done!\n", __func__);
}
void dtmb_write_reg(int reg_addr, int reg_data)
{
if (!get_dtvpll_init_flag())
return;
mutex_lock(&mp);
/* printk("[demod][write]%x,data is %x\n",(addr),data);*/
writel(reg_data, gbase_dtmb() + (reg_addr << 2));
mutex_unlock(&mp);
}
unsigned int dtmb_read_reg(unsigned int reg_addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
/*mutex_lock(&mp);*/
tmp = readl(gbase_dtmb() + (reg_addr << 2));
/*mutex_unlock(&mp);*/
return tmp;
}
void dtmb_write_reg_bits(u32 addr, const u32 data, const u32 start, const u32 len)
{
unsigned int val;
if (!get_dtvpll_init_flag())
return;
val = dtmb_read_reg(addr);
val &= ~(((1L << (len)) - 1) << (start));
val |= (((data) & ((1L << (len)) - 1)) << (start));
dtmb_write_reg(addr, val);
}
void dvbt_isdbt_wr_reg(unsigned int addr, unsigned int data)
{
if (!get_dtvpll_init_flag())
return;
/*mutex_lock(&mp);*/
writel(data, gbase_dvbt_isdbt() + addr);
/*mutex_unlock(&mp);*/
}
void dvbt_isdtb_wr_reg_new(unsigned int addr, unsigned int data)
{
if (!get_dtvpll_init_flag())
return;
/*mutex_lock(&mp);*/
writel(data, gbase_dvbt_isdbt() + (addr << 2));
/*mutex_unlock(&mp);*/
}
void dvbt_isdbt_wr_bits_new(u32 reg_addr, const u32 reg_data,
const u32 start, const u32 len)
{
unsigned int val;
if (!get_dtvpll_init_flag())
return;
/*mutex_lock(&mp);*/
val = readl(gbase_dvbt_isdbt() + (reg_addr << 2));
val &= ~(((1L << (len)) - 1) << (start));
val |= (((reg_data) & ((1L << (len)) - 1)) << (start));
writel(val, gbase_dvbt_isdbt() + (reg_addr << 2));
/*mutex_unlock(&mp);*/
}
unsigned int dvbt_isdbt_rd_reg(unsigned int addr)
{
unsigned int tmp = 0;
if (!get_dtvpll_init_flag())
return 0;
/*mutex_lock(&mp);*/
tmp = readl(gbase_dvbt_isdbt() + addr);
/*mutex_unlock(&mp);*/
return tmp;
}
unsigned int dvbt_isdbt_rd_reg_new(unsigned int addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
tmp = readl(gbase_dvbt_isdbt() + (addr << 2));
mutex_unlock(&mp);
return tmp;
}
void dvbt_t2_wrb(unsigned int addr, char data)
{
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!get_dtvpll_init_flag() || unlikely(!devp))
return;
mutex_lock(&mp);
__raw_writeb(data, gbase_dvbt_t2() + addr);
if (devp->print_on)
PR_INFO("t2 wrB 0x%x=0x%x\n", addr, data);
mutex_unlock(&mp);
}
void dvbt_t2_wr_byte_bits(u32 addr, const u32 data, const u32 start, const u32 len)
{
unsigned int val;
if (!get_dtvpll_init_flag())
return;
val = dvbt_t2_rdb(addr);
val &= ~(((1L << (len)) - 1) << (start));
val |= (((data) & ((1L << (len)) - 1)) << (start));
dvbt_t2_wrb(addr, val);
}
void dvbt_t2_write_w(unsigned int addr, unsigned int data)
{
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!get_dtvpll_init_flag() || unlikely(!devp))
return;
writel(data, gbase_dvbt_t2() + addr);
if (devp->print_on)
PR_INFO("t2 wrW 0x%x=0x%x\n", addr, data);
}
void dvbt_t2_wr_word_bits(u32 addr, const u32 data, const u32 start, const u32 len)
{
unsigned int val;
if (!get_dtvpll_init_flag())
return;
/*mutex_lock(&mp);*/
val = readl(gbase_dvbt_t2() + addr);
val &= ~(((1L << (len)) - 1) << (start));
val |= (((data) & ((1L << (len)) - 1)) << (start));
writel(val, gbase_dvbt_t2() + addr);
/*mutex_unlock(&mp);*/
}
unsigned int dvbt_t2_read_w(unsigned int addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
tmp = readl(gbase_dvbt_t2() + addr);
return tmp;
}
char dvbt_t2_rdb(unsigned int addr)
{
char tmp = 0;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
tmp = __raw_readb(gbase_dvbt_t2() + addr);
mutex_unlock(&mp);
return tmp;
}
/* only for T5D T2 use, have to set top 0x10 = 0x97 before any access */
void riscv_ctl_write_reg(unsigned int addr, unsigned int data)
{
dvbt_t2_write_w(addr, data);
}
void dvbs_wr_byte(unsigned int addr, char data)
{
if (!get_dtvpll_init_flag())
return;
/*mutex_lock(&mp);*/
__raw_writeb(data, gbase_dvbs() + addr);
/*mutex_unlock(&mp);*/
}
char dvbs_rd_byte(unsigned int addr)
{
char tmp = 0;
if (!get_dtvpll_init_flag())
return 0;
/*mutex_lock(&mp);*/
tmp = __raw_readb(gbase_dvbs() + addr);
/*mutex_unlock(&mp);*/
return tmp;
}
void dvbs_write_bits(u32 reg_addr, const u32 reg_data,
const u32 start, const u32 len)
{
unsigned int val;
if (!get_dtvpll_init_flag())
return;
/*mutex_lock(&mp);*/
val = readl(gbase_dvbs() + (reg_addr << 2));
val &= ~(((1L << (len)) - 1) << (start));
val |= (((reg_data) & ((1L << (len)) - 1)) << (start));
writel(val, gbase_dvbs() + (reg_addr << 2));
/*mutex_unlock(&mp);*/
}
void atsc_write_reg(unsigned int reg_addr, unsigned int reg_data)
{
unsigned int data;
if (!get_dtvpll_init_flag())
return;
data = (reg_addr & 0xffff) << 8 | (reg_data & 0xff);
mutex_lock(&mp);
/* printk("[demod][write]%x,data is %x\n",(addr),data);*/
writel(data, gbase_atsc());
mutex_unlock(&mp);
}
unsigned int atsc_read_reg(unsigned int reg_addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
writel((reg_addr & 0xffff) << 8, gbase_atsc() + 4);
tmp = readl(gbase_atsc());
mutex_unlock(&mp);
return tmp & 0xff;
}
/*TL1*/
void atsc_write_reg_v4(unsigned int addr, unsigned int data)
{
if (!get_dtvpll_init_flag())
return;
mutex_lock(&mp);
writel(data, gbase_atsc() + (addr << 2));
mutex_unlock(&mp);
}
void atsc_write_reg_bits_v4(u32 addr, const u32 data, const u32 start, const u32 len)
{
unsigned int val;
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!get_dtvpll_init_flag() || unlikely(!devp))
return;
mutex_lock(&mp);
val = readl(gbase_atsc() + (addr << 2));
val &= ~(((1L << (len)) - 1) << (start));
val |= (((data) & ((1L << (len)) - 1)) << (start));
writel(val, gbase_atsc() + (addr << 2));
mutex_unlock(&mp);
if (devp->print_on)
PR_INFO("atsc wrBit 0x%x=0x%x, s:%d,l:%d\n", addr, data, start, len);
}
unsigned int atsc_read_reg_v4(unsigned int addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
tmp = readl(gbase_atsc() + (addr << 2));
mutex_unlock(&mp);
return tmp;
}
unsigned int atsc_read_iqr_reg(void)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
tmp = readl(gbase_atsc() + 8);
mutex_unlock(&mp);
PR_DBG("[atsc irq] is %x\n", tmp);
return tmp & 0xffffffff;
}
void demod_init_mutex(void)
{
mutex_init(&mp);
}
int demod_set_sys(struct aml_dtvdemod *demod, struct aml_demod_sys *demod_sys)
{
unsigned int clk_adc, clk_dem;
int nco_rate;
struct amldtvdemod_device_s *devp = (struct amldtvdemod_device_s *)demod->priv;
clk_adc = demod_sys->adc_clk;
clk_dem = demod_sys->demod_clk;
nco_rate = (clk_adc * 256) / clk_dem + 2;
PR_DBG("%s: clk_adc is %d, clk_demod is %d.\n", __func__, clk_adc, clk_dem);
clocks_set_sys_defaults(demod, clk_adc);
/* set adc clk */
demod_set_adc_core_clk(clk_adc, clk_dem, &demod->demod_status);
switch (demod->demod_status.delsys) {
case SYS_DTMB:
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
demod_top_write_reg(DEMOD_TOP_REGC, 0x10);
usleep_range(1000, 1001);
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
front_write_bits(AFIFO_ADC, nco_rate,
AFIFO_NCO_RATE_BIT, AFIFO_NCO_RATE_WID);
front_write_bits(AFIFO_ADC, 1, ADC_2S_COMPLEMENT_BIT,
ADC_2S_COMPLEMENT_WID);
front_write_bits(TEST_BUS, 1, DC_ARB_EN_BIT, DC_ARB_EN_WID);
} else {
demod_top_write_reg(DEMOD_TOP_REGC, 0x8);
PR_DBG("[open arbit]dtmb\n");
}
break;
case SYS_ISDBT:
if (is_meson_txlx_cpu()) {
demod_top_write_reg(DEMOD_TOP_REGC, 0x8);
} else if (devp->data->hw_ver >= DTVDEMOD_HW_T5D) {
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
demod_top_write_reg(DEMOD_TOP_REGC, 0x10);
usleep_range(1000, 1001);
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
front_write_bits(AFIFO_ADC, nco_rate, AFIFO_NCO_RATE_BIT,
AFIFO_NCO_RATE_WID);
front_write_bits(AFIFO_ADC, 1, ADC_2S_COMPLEMENT_BIT,
ADC_2S_COMPLEMENT_WID);
front_write_reg(SFIFO_OUT_LENS, 1);
front_write_bits(TEST_BUS, 1, DC_ARB_EN_BIT, DC_ARB_EN_WID);
}
PR_DBG("[open arbit]dvbt,txlx\n");
break;
case SYS_ATSC:
case SYS_ATSCMH:
case SYS_DVBC_ANNEX_B:
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (devp->data->hw_ver == DTVDEMOD_HW_S4D) {
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
demod_top_write_reg(DEMOD_TOP_REGC, 0x10);
usleep_range(1000, 2000);
demod_top_write_reg(DEMOD_TOP_REGC, 0xcc0011);
front_write_bits(0x6c, nco_rate,
AFIFO_NCO_RATE_BIT,
AFIFO_NCO_RATE_WID);
} else {
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
demod_top_write_reg(DEMOD_TOP_REGC, 0x10);
usleep_range(1000, 1001);
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
front_write_bits(AFIFO_ADC, nco_rate,
AFIFO_NCO_RATE_BIT,
AFIFO_NCO_RATE_WID);
}
front_write_bits(AFIFO_ADC, 1, ADC_2S_COMPLEMENT_BIT,
ADC_2S_COMPLEMENT_WID);
}
break;
case SYS_DVBC_ANNEX_A:
case SYS_DVBC_ANNEX_C:
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1)) {
if (devp->data->hw_ver == DTVDEMOD_HW_S4 ||
devp->data->hw_ver == DTVDEMOD_HW_S4D) {
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
demod_top_write_reg(DEMOD_TOP_REGC, 0x10);
usleep_range(1000, 2000);
demod_top_write_reg(DEMOD_TOP_REGC, 0xcc0011);
front_write_bits(AFIFO_ADC_S4D, nco_rate,
AFIFO_NCO_RATE_BIT, AFIFO_NCO_RATE_WID);
} else {
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
demod_top_write_reg(DEMOD_TOP_REGC, 0x10);
usleep_range(1000, 2000);
demod_top_write_reg(DEMOD_TOP_REGC, 0x11);
front_write_bits(AFIFO_ADC, nco_rate, AFIFO_NCO_RATE_BIT,
AFIFO_NCO_RATE_WID);
}
front_write_reg(SFIFO_OUT_LENS, 0x05);
front_write_bits(AFIFO_ADC, 1, ADC_2S_COMPLEMENT_BIT,
ADC_2S_COMPLEMENT_WID);
}
break;
case SYS_DVBT:
case SYS_DVBT2:
break;
case SYS_DVBS:
case SYS_DVBS2:
if (devp->data->hw_ver >= DTVDEMOD_HW_T5D) {
nco_rate = 0x0;
if (devp->data->hw_ver >= DTVDEMOD_HW_T3) {
demod_top_write_reg(DEMOD_TOP_REGC, 0x80220011);
demod_top_write_reg(DEMOD_TOP_REGC, 0x80220010);
usleep_range(1000, 1001);
demod_top_write_reg(DEMOD_TOP_REGC, 0x80220011);
} else {
demod_top_write_reg(DEMOD_TOP_REGC, 0x220011);
demod_top_write_reg(DEMOD_TOP_REGC, 0x220010);
usleep_range(1000, 1001);
demod_top_write_reg(DEMOD_TOP_REGC, 0x220011);
}
if (devp->data->hw_ver == DTVDEMOD_HW_S4D)
front_write_bits(AFIFO_ADC_S4D, nco_rate,
AFIFO_NCO_RATE_BIT,
AFIFO_NCO_RATE_WID);
else
front_write_bits(AFIFO_ADC, nco_rate,
AFIFO_NCO_RATE_BIT,
AFIFO_NCO_RATE_WID);
front_write_reg(SFIFO_OUT_LENS, 0x0);
front_write_reg(0x22, 0x7200a06);
}
break;
default:
break;
}
PR_ERR("%s:done!\n", __func__);
return 0;
}
/*TL1*/
void set_j83b_filter_reg_v4(struct aml_dtvdemod *demod)
{
//j83_1
qam_write_reg(demod, 0x40, 0x3F010201);//25M:0x36333c0d
qam_write_reg(demod, 0x41, 0xA003A3B);//25M:0xa110d01
qam_write_reg(demod, 0x42, 0xE1EE030E);//25M:0xf0e4ea7a
qam_write_reg(demod, 0x43, 0x2601F2);//25M:0x3c0010
qam_write_reg(demod, 0x44, 0x9B006B);//25M:0x7e0065
//j83_2
qam_write_reg(demod, 0x45, 0xb3a1905);
qam_write_reg(demod, 0x46, 0x1c396e07);
qam_write_reg(demod, 0x47, 0x3801cc08);
qam_write_reg(demod, 0x48, 0x10800a2);
qam_write_reg(demod, 0x49, 0x53b1f03);
qam_write_reg(demod, 0x4a, 0x18377407);
qam_write_reg(demod, 0x4b, 0x3401cf0b);
qam_write_reg(demod, 0x4c, 0x10d00a1);
}
void demod_set_reg(struct aml_dtvdemod *demod, struct aml_demod_reg *demod_reg)
{
if (fpga_version == 1) {
#if defined DEMOD_FPGA_VERSION
fpga_write_reg(demod_reg->mode, demod_reg->addr,
demod_reg->val);
#endif
} else {
switch (demod_reg->mode) {
case REG_MODE_CFG:
demod_reg->addr = demod_reg->addr * 4
+ gphybase_demod() + DEMOD_CFG_BASE;
break;
case REG_MODE_BASE:
demod_reg->addr = demod_reg->addr + gphybase_demod();
break;
default:
break;
}
switch (demod_reg->mode) {
case REG_MODE_DTMB:
dtmb_write_reg(demod_reg->addr, demod_reg->val);
break;
case REG_MODE_DVBT_ISDBT:
if (demod_reg->access_mode == ACCESS_WORD)
dvbt_isdtb_wr_reg_new(demod_reg->addr, demod_reg->val);
else if (demod_reg->access_mode == ACCESS_BITS)
dvbt_isdbt_wr_bits_new(demod_reg->addr, demod_reg->val,
demod_reg->start_bit, demod_reg->bit_width);
break;
case REG_MODE_DVBT_T2:
if (demod_reg->access_mode == ACCESS_BYTE)
dvbt_t2_wrb(demod_reg->addr, demod_reg->val);
break;
case REG_MODE_ATSC:
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
atsc_write_reg_v4(demod_reg->addr, demod_reg->val);
else
atsc_write_reg(demod_reg->addr, demod_reg->val);
break;
case REG_MODE_OTHERS:
demod_set_cbus_reg(demod_reg->val, demod_reg->addr);
break;
case REG_MODE_DVBC_J83B:
qam_write_reg(demod, demod_reg->addr, demod_reg->val);
break;
case REG_MODE_FRONT:
if (demod_reg->access_mode == ACCESS_BITS)
front_write_bits(demod_reg->addr, demod_reg->val,
demod_reg->start_bit, demod_reg->bit_width);
else if (demod_reg->access_mode == ACCESS_WORD)
front_write_reg(demod_reg->addr, demod_reg->val);
break;
case REG_MODE_TOP:
if (demod_reg->access_mode == ACCESS_BITS)
demod_top_write_bits(demod_reg->addr, demod_reg->val,
demod_reg->start_bit, demod_reg->bit_width);
else if (demod_reg->access_mode == ACCESS_WORD)
demod_top_write_reg(demod_reg->addr, demod_reg->val);
break;
case REG_MODE_COLLECT_DATA:
apb_write_reg_collect(demod_reg->addr, demod_reg->val);
break;
default:
demod_set_demod_reg(demod_reg->val, demod_reg->addr);
break;
}
}
}
void demod_get_reg(struct aml_dtvdemod *demod, struct aml_demod_reg *demod_reg)
{
if (fpga_version == 1) {
#if defined DEMOD_FPGA_VERSION
demod_reg->val = fpga_read_reg(demod_reg->mode,
demod_reg->addr);
#endif
} else {
if (demod_reg->mode == REG_MODE_CFG)
demod_reg->addr = demod_reg->addr * 4
+ gphybase_demod() + DEMOD_CFG_BASE;
else if (demod_reg->mode == REG_MODE_BASE)
demod_reg->addr = demod_reg->addr + gphybase_demod();
switch (demod_reg->mode) {
case REG_MODE_DTMB:
demod_reg->val = dtmb_read_reg(demod_reg->addr);
break;
case REG_MODE_DVBT_ISDBT:
demod_reg->val = dvbt_isdbt_rd_reg_new(demod_reg->addr);
break;
case REG_MODE_DVBT_T2:
if (demod_reg->access_mode == ACCESS_BYTE)
demod_reg->val = dvbt_t2_rdb(demod_reg->addr);
break;
case REG_MODE_ATSC:
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
demod_reg->val = atsc_read_reg_v4(demod_reg->addr);
else
demod_reg->val = atsc_read_reg(demod_reg->addr);
break;
case REG_MODE_DVBC_J83B:
demod_reg->val = qam_read_reg(demod, demod_reg->addr);
break;
case REG_MODE_FRONT:
demod_reg->val = front_read_reg(demod_reg->addr);
break;
case REG_MODE_TOP:
demod_reg->val = demod_top_read_reg(demod_reg->addr);
break;
case REG_MODE_OTHERS:
demod_reg->val = demod_read_cbus_reg(demod_reg->addr);
break;
case REG_MODE_COLLECT_DATA:
demod_reg->val = apb_read_reg_collect(demod_reg->addr);
break;
default:
demod_reg->val = demod_read_demod_reg(demod_reg->addr);
break;
}
}
}
void apb_write_reg_collect(unsigned int addr, unsigned int data)
{
writel(data, ((void __iomem *)(phys_to_virt(addr))));
/* *(volatile unsigned int*)addr = data; */
}
unsigned long apb_read_reg_collect(unsigned long addr)
{
unsigned long tmp;
tmp = readl((void __iomem *)(phys_to_virt(addr)));
return tmp & 0xffffffff;
}
void apb_write_reg(unsigned int addr, unsigned int data)
{
demod_set_demod_reg(data, addr);
}
unsigned long apb_read_reg_high(unsigned long addr)
{
return 0;
}
unsigned long apb_read_reg(unsigned long addr)
{
return demod_read_demod_reg(addr);
}
int app_apb_read_reg(int addr)
{
addr = DTMB_TOP_ADDR(addr);
return (int)demod_read_demod_reg(addr);
}
int app_apb_write_reg(int addr, int data)
{
addr = DTMB_TOP_ADDR(addr);
demod_set_demod_reg(data, addr);
return 0;
}
#if 0
void monitor_isdbt(void)
{
int SNR;
int SNR_SP = 500;
int SNR_TPS = 0;
int SNR_CP = 0;
int timeStamp = 0;
int SFO_residual = 0;
int SFO_esti = 0;
int FCFO_esti = 0;
int FCFO_residual = 0;
int AGC_Gain = 0;
int RF_AGC = 0;
int Signal_power = 0;
int FECFlag = 0;
int EQ_seg_ratio = 0;
int tps_0 = 0;
int tps_1 = 0;
int tps_2 = 0;
int time_stamp;
int SFO;
int FCFO;
int timing_adj;
int RS_CorrectNum;
int cnt;
int tmpAGCGain;
tmpAGCGain = 0;
cnt = 0;
/* app_apb_write_reg(0x8, app_apb_read_reg(0x8) & ~(1 << 17));*/
/* // TPS symbol index update : active high */
time_stamp = app_apb_read_reg(0x07) & 0xffff;
SNR = app_apb_read_reg(0x0a);
FECFlag = (app_apb_read_reg(0x00) >> 11) & 0x3;
SFO = app_apb_read_reg(0x47) & 0xfff;
SFO_esti = app_apb_read_reg(0x60) & 0xfff;
FCFO_esti = (app_apb_read_reg(0x60) >> 11) & 0xfff;
FCFO = (app_apb_read_reg(0x26)) & 0xffffff;
RF_AGC = app_apb_read_reg(0x0c) & 0x1fff;
timing_adj = app_apb_read_reg(0x6f) & 0x1fff;
RS_CorrectNum = app_apb_read_reg(0xc1) & 0xfffff;
Signal_power = (app_apb_read_reg(0x1b)) & 0x1ff;
EQ_seg_ratio = app_apb_read_reg(0x6e) & 0x3ffff;
tps_0 = app_apb_read_reg(0x64);
tps_1 = app_apb_read_reg(0x65);
tps_2 = app_apb_read_reg(0x66) & 0xf;
timeStamp = (time_stamp >> 8) * 68 + (time_stamp & 0x7f);
SFO_residual = (SFO > 0x7ff) ? (SFO - 0x1000) : SFO;
FCFO_residual = (FCFO > 0x7fffff) ? (FCFO - 0x1000000) : FCFO;
/* RF_AGC = (RF_AGC>0x3ff)? (RF_AGC - 0x800): RF_AGC; */
FCFO_esti = (FCFO_esti > 0x7ff) ? (FCFO_esti - 0x1000) : FCFO_esti;
SNR_CP = (SNR) & 0x3ff;
SNR_TPS = (SNR >> 10) & 0x3ff;
SNR_SP = (SNR >> 20) & 0x3ff;
SNR_SP = (SNR_SP > 0x1ff) ? SNR_SP - 0x400 : SNR_SP;
SNR_TPS = (SNR_TPS > 0x1ff) ? SNR_TPS - 0x400 : SNR_TPS;
SNR_CP = (SNR_CP > 0x1ff) ? SNR_CP - 0x400 : SNR_CP;
AGC_Gain = tmpAGCGain >> 4;
tmpAGCGain = (AGC_Gain > 0x3ff) ? AGC_Gain - 0x800 : AGC_Gain;
timing_adj = (timing_adj > 0xfff) ? timing_adj - 0x2000 : timing_adj;
EQ_seg_ratio =
(EQ_seg_ratio > 0x1ffff) ? EQ_seg_ratio - 0x40000 : EQ_seg_ratio;
PR_DBG
("T %4x SP %3d TPS %3d CP %3d EQS %8x RSC %4d",
app_apb_read_reg(0xbf)
, SNR_SP, SNR_TPS, SNR_CP
/* ,EQ_seg_ratio */
, app_apb_read_reg(0x62)
, RS_CorrectNum);
PR_DBG
("SFO %4d FCFO %4d Vit %4x Timing %3d SigP %3x",
SFO_residual, FCFO_residual, RF_AGC, timing_adj,
Signal_power);
PR_DBG
("FEC %x RSErr %8x ReSyn %x tps %03x%08x",
FECFlag, app_apb_read_reg(0x0b)
, (app_apb_read_reg(0xc0) >> 20) & 0xff,
app_apb_read_reg(0x05) & 0xfff, app_apb_read_reg(0x04)
);
PR_DBG("\n");
}
#endif
/*dvbc_write_reg -> apb_write_reg in dvbc_func*/
/*dvbc_read_reg -> apb_read_reg in dvbc_func*/
#if 0
void dvbc_write_reg(unsigned int addr, unsigned int data)
{
demod_set_demod_reg(data, ddemod_reg_base + addr);
}
unsigned int dvbc_read_reg(unsigned int addr)
{
return demod_read_demod_reg(ddemod_reg_base + addr);
}
#else
void dvbc_write_reg(unsigned int addr, unsigned int data)
{
/*mutex_lock(&mp);*/
/* printk("[demod][write]%x,data is %x\n",(addr),data);*/
writel(data, gbase_dvbc() + addr);
/*mutex_unlock(&mp);*/
}
unsigned int dvbc_read_reg(unsigned int addr)
{
unsigned int tmp;
/*mutex_lock(&mp);*/
tmp = readl(gbase_dvbc() + addr);
/*mutex_unlock(&mp);*/
return tmp;
}
#endif
void demod_top_write_reg(unsigned int addr, unsigned int data)
{
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (unlikely(!devp))
return;
mutex_lock(&mp);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
writel(data, gbase_demod() + (addr << 2));
else
writel(data, gbase_demod() + addr);
mutex_unlock(&mp);
if (devp->print_on)
PR_INFO("top wrW 0x%x=0x%x\n", addr, data);
}
void demod_top_write_bits(u32 reg_addr, const u32 reg_data, const u32 start, const u32 len)
{
unsigned int val;
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!get_dtvpll_init_flag() || unlikely(!devp))
return;
mutex_lock(&mp);
val = readl(gbase_demod() + (reg_addr << 2));
val &= ~(((1L << (len)) - 1) << (start));
val |= (((reg_data) & ((1L << (len)) - 1)) << (start));
writel(val, gbase_demod() + (reg_addr << 2));
if (devp->print_on)
PR_INFO("top wrBit 0x%x=0x%x,s:%d,l:%d\n", reg_addr, reg_data, start, len);
mutex_unlock(&mp);
}
unsigned int demod_top_read_reg(unsigned int addr)
{
unsigned int tmp;
mutex_lock(&mp);
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
tmp = readl(gbase_demod() + (addr << 2));
else
tmp = readl(gbase_demod() + addr);
mutex_unlock(&mp);
return tmp;
}
/*TL1*/
void front_write_reg(unsigned int addr, unsigned int data)
{
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!get_dtvpll_init_flag() || unlikely(!devp))
return;
mutex_lock(&mp);
writel(data, gbase_front() + (addr << 2));
if (devp->print_on)
PR_INFO("front wrW 0x%x=0x%x\n", addr, data);
mutex_unlock(&mp);
}
void front_write_bits(u32 reg_addr, const u32 reg_data, const u32 start, const u32 len)
{
unsigned int val;
struct amldtvdemod_device_s *devp = dtvdemod_get_dev();
if (!get_dtvpll_init_flag() || unlikely(!devp))
return;
mutex_lock(&mp);
val = readl(gbase_front() + (reg_addr << 2));
val &= ~(((1L << (len)) - 1) << (start));
val |= (((reg_data) & ((1L << (len)) - 1)) << (start));
writel(val, gbase_front() + (reg_addr << 2));
if (devp->print_on)
PR_INFO("front wrBit 0x%x=0x%x, s:%d,l:%d\n", reg_addr, reg_data, start, len);
mutex_unlock(&mp);
}
unsigned int front_read_reg(unsigned int addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
tmp = readl(gbase_front() + (addr << 2));
mutex_unlock(&mp);
return tmp;
}
void isdbt_write_reg_v4(unsigned int addr, unsigned int data)
{
mutex_lock(&mp);
/* printk("[demod][write]%x,data is %x\n",(addr),data);*/
writel(data, gbase_isdbt() + addr);
mutex_unlock(&mp);
}
unsigned int isdbt_read_reg_v4(unsigned int addr)
{
unsigned int tmp;
mutex_lock(&mp);
tmp = readl(gbase_isdbt() + addr);
mutex_unlock(&mp);
return tmp;
}
/*dvbc v3:*/
void qam_write_reg(struct aml_dtvdemod *demod,
unsigned int reg_addr, unsigned int reg_data)
{
struct amldtvdemod_device_s *devp = (struct amldtvdemod_device_s *)demod->priv;
if (!get_dtvpll_init_flag())
return;
if (devp && devp->stop_reg_wr)
return;
mutex_lock(&mp);
if (demod->dvbc_sel)
writel(reg_data, gbase_dvbc_2() + (reg_addr << 2));
else
writel(reg_data, gbase_dvbc() + (reg_addr << 2));
mutex_unlock(&mp);
}
unsigned int qam_read_reg(struct aml_dtvdemod *demod, unsigned int reg_addr)
{
unsigned int tmp;
if (!get_dtvpll_init_flag())
return 0;
mutex_lock(&mp);
if (demod->dvbc_sel)
tmp = readl(gbase_dvbc_2() + (reg_addr << 2));
else
tmp = readl(gbase_dvbc() + (reg_addr << 2));
mutex_unlock(&mp);
return tmp;
}
void qam_write_bits(struct aml_dtvdemod *demod,
u32 reg_addr, const u32 reg_data,
const u32 start, const u32 len)
{
unsigned int val;
struct amldtvdemod_device_s *devp = (struct amldtvdemod_device_s *)demod->priv;
if (!get_dtvpll_init_flag())
return;
if (devp && devp->stop_reg_wr)
return;
mutex_lock(&mp);
if (demod->dvbc_sel)
val = readl(gbase_dvbc_2() + (reg_addr << 2));
else
val = readl(gbase_dvbc() + (reg_addr << 2));
val &= ~(((1L << (len)) - 1) << (start));
val |= (((reg_data) & ((1L << (len)) - 1)) << (start));
if (demod->dvbc_sel)
writel(val, gbase_dvbc_2() + (reg_addr << 2));
else
writel(val, gbase_dvbc() + (reg_addr << 2));
mutex_unlock(&mp);
}
int dd_hiu_reg_write(unsigned int reg, unsigned int val)
{
mutex_lock(&mp);
writel(val, gbase_iohiu() + (reg << 2));
mutex_unlock(&mp);
return 0;
}
unsigned int dd_hiu_reg_read(unsigned int addr)
{
unsigned int tmp;
mutex_lock(&mp);
tmp = readl(gbase_iohiu() + (addr << 2));
mutex_unlock(&mp);
return tmp;
}
int reset_reg_write(unsigned int reg, unsigned int val)
{
mutex_lock(&mp);
writel(val, gbase_reset() + reg);
mutex_unlock(&mp);
return 0;
}
unsigned int reset_reg_read(unsigned int addr)
{
unsigned int tmp;
mutex_lock(&mp);
tmp = readl(gbase_reset() + addr);
mutex_unlock(&mp);
return tmp;
}
void dtvdemod_dmc_reg_write(unsigned int reg, unsigned int val)
{
writel(val, gbase_dmc() + reg);
}
unsigned int dtvdemod_dmc_reg_read(unsigned int addr)
{
unsigned int tmp;
tmp = readl(gbase_dmc() + addr);
return tmp;
}
void dtvdemod_ddr_reg_write(unsigned int reg, unsigned int val)
{
writel(val, gbase_ddr() + reg);
}
unsigned int dtvdemod_ddr_reg_read(unsigned int addr)
{
unsigned int tmp;
tmp = readl(gbase_ddr() + addr);
return tmp;
}
void demod_set_demod_default(void)
{
if (cpu_after_eq(MESON_CPU_MAJOR_ID_TL1))
return;
demod_top_write_reg(DEMOD_TOP_REG0, DEMOD_REG0_VALUE);
demod_top_write_reg(DEMOD_TOP_REG4, DEMOD_REG4_VALUE);
demod_top_write_reg(DEMOD_TOP_REG8, DEMOD_REG8_VALUE);
}