blob: cf2ea8163947e15d0e3da2233f1cd632c9d6a747 [file] [log] [blame]
/*
* Copyright (C) 2017 Amlogic, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Description:
*/
#include <linux/kernel.h>
#include <linux/i2c.h>
#include <linux/delay.h>
#include <linux/dvb/aml_demod.h>
#include "demod_func.h"
#include <linux/kthread.h>
static int debug_amldvbc = 1;
#define dprintk(a ...) do { if (debug_amldvbc) printk(a); } while (0)
static struct task_struct *cci_task;
int cciflag;
struct timer_list mytimer;
static void dvbc_cci_timer(unsigned long data)
{
#if 0
int count;
int maxCCI_p, re, im, j, i, times, maxCCI, sum, sum1, reg_0xf0, tmp1,
tmp, tmp2, reg_0xa8, reg_0xac;
int reg_0xa8_t, reg_0xac_t;
count = 100;
if ((((apb_read_reg(QAM_BASE + 0x18)) & 0x1) == 1)) {
dprintk("[cci]lock ");
if (cciflag == 0) {
apb_write_reg(QAM_BASE + 0xa8, 0);
cciflag = 0;
}
dprintk("\n");
mdelay(500);
mod_timer(&mytimer, jiffies + 2 * HZ);
return;
}
if (cciflag == 1) {
dprintk("[cci]cciflag is 1,wait 20\n");
mdelay(20000);
}
times = 300;
tmp = 0x2be2be3;
/*0x2ae4772; IF = 6M, fs = 35M, dec2hex(round(8*IF/fs*2^25)) */
tmp2 = 0x2000;
tmp1 = 8;
reg_0xa8 = 0xc0000000; /* bypass CCI */
reg_0xac = 0xc0000000; /* bypass CCI */
maxCCI = 0;
maxCCI_p = 0;
for (i = 0; i < times; i++) {
/*reg_0xa8 = app_apb_read_reg(0xa8); */
reg_0xa8_t = reg_0xa8 + tmp + i * tmp2;
apb_write_reg(QAM_BASE + 0xa8, reg_0xa8_t);
reg_0xac_t = reg_0xac + tmp - i * tmp2;
apb_write_reg(QAM_BASE + 0xac, reg_0xac_t);
sum = 0;
sum1 = 0;
for (j = 0; j < tmp1; j++) {
/* msleep(20); */
/* mdelay(20); */
reg_0xf0 = apb_read_reg(QAM_BASE + 0xf0);
re = (reg_0xf0 >> 24) & 0xff;
im = (reg_0xf0 >> 16) & 0xff;
if (re > 127)
/*re = re - 256; */
re = 256 - re;
if (im > 127)
/*im = im - 256; */
im = 256 - im;
sum += re + im;
re = (reg_0xf0 >> 8) & 0xff;
im = (reg_0xf0 >> 0) & 0xff;
if (re > 127)
/*re = re - 256; */
re = 256 - re;
if (im > 127)
/*im = im - 256; */
im = 256 - im;
sum1 += re + im;
}
sum = sum / tmp1;
sum1 = sum1 / tmp1;
if (sum1 > sum) {
sum = sum1;
reg_0xa8_t = reg_0xac_t;
}
if (sum > maxCCI) {
maxCCI = sum;
if (maxCCI > 24)
maxCCI_p = reg_0xa8_t & 0x7fffffff;
}
if ((sum < 24) && (maxCCI_p > 0))
break; /* stop CCI detect. */
}
if (maxCCI_p > 0) {
apb_write_reg(QAM_BASE + 0xa8, maxCCI_p & 0x7fffffff);
/* enable CCI */
apb_write_reg(QAM_BASE + 0xac, maxCCI_p & 0x7fffffff);
/* enable CCI */
/* if(dvbc.mode == 4) // 256QAM */
apb_write_reg(QAM_BASE + 0x54, 0xa25705fa);
/**/ cciflag = 1;
mdelay(1000);
} else {
dprintk
("[cci] ------------ find NO CCI -------------------\n");
cciflag = 0;
}
dprintk("[cci][%s]--------------------------\n", __func__);
mod_timer(&mytimer, jiffies + 2 * HZ);
return;
/* }*/
#endif
}
int dvbc_timer_init(void)
{
dprintk("%s\n", __func__);
setup_timer(&mytimer, dvbc_cci_timer, (unsigned long)"Hello, world!");
mytimer.expires = jiffies + 2 * HZ;
add_timer(&mytimer);
return 0;
}
void dvbc_timer_exit(void)
{
dprintk("%s\n", __func__);
del_timer(&mytimer);
}
int dvbc_cci_task(void *data)
{
int count;
int maxCCI_p, re, im, j, i, times, maxCCI, sum, sum1, reg_0xf0, tmp1,
tmp, tmp2, reg_0xa8, reg_0xac;
int reg_0xa8_t, reg_0xac_t;
count = 100;
while (1) {
msleep(200);
if ((((apb_read_reg(QAM_BASE + 0x18)) & 0x1) == 1)) {
dprintk("[cci]lock ");
if (cciflag == 0) {
apb_write_reg(QAM_BASE + 0xa8, 0);
apb_write_reg(QAM_BASE + 0xac, 0);
dprintk("no cci ");
cciflag = 0;
}
dprintk("\n");
msleep(500);
continue;
}
if (cciflag == 1) {
dprintk("[cci]cciflag is 1,wait 20\n");
msleep(20000);
}
times = 300;
tmp = 0x2be2be3;
/*0x2ae4772; IF = 6M,fs = 35M, dec2hex(round(8*IF/fs*2^25)) */
tmp2 = 0x2000;
tmp1 = 8;
reg_0xa8 = 0xc0000000; /* bypass CCI */
reg_0xac = 0xc0000000; /* bypass CCI */
maxCCI = 0;
maxCCI_p = 0;
for (i = 0; i < times; i++) {
/*reg_0xa8 = app_apb_read_reg(0xa8); */
reg_0xa8_t = reg_0xa8 + tmp + i * tmp2;
apb_write_reg(QAM_BASE + 0xa8, reg_0xa8_t);
reg_0xac_t = reg_0xac + tmp - i * tmp2;
apb_write_reg(QAM_BASE + 0xac, reg_0xac_t);
sum = 0;
sum1 = 0;
for (j = 0; j < tmp1; j++) {
/* msleep(1); */
reg_0xf0 = apb_read_reg(QAM_BASE + 0xf0);
re = (reg_0xf0 >> 24) & 0xff;
im = (reg_0xf0 >> 16) & 0xff;
if (re > 127)
/*re = re - 256; */
re = 256 - re;
if (im > 127)
/*im = im - 256; */
im = 256 - im;
sum += re + im;
re = (reg_0xf0 >> 8) & 0xff;
im = (reg_0xf0 >> 0) & 0xff;
if (re > 127)
/*re = re - 256; */
re = 256 - re;
if (im > 127)
/*im = im - 256; */
im = 256 - im;
sum1 += re + im;
}
sum = sum / tmp1;
sum1 = sum1 / tmp1;
if (sum1 > sum) {
sum = sum1;
reg_0xa8_t = reg_0xac_t;
}
if (sum > maxCCI) {
maxCCI = sum;
if (maxCCI > 24)
maxCCI_p = reg_0xa8_t & 0x7fffffff;
}
if ((sum < 24) && (maxCCI_p > 0))
break; /* stop CCI detect. */
}
if (maxCCI_p > 0) {
apb_write_reg(QAM_BASE + 0xa8, maxCCI_p & 0x7fffffff);
/* enable CCI */
apb_write_reg(QAM_BASE + 0xac, maxCCI_p & 0x7fffffff);
/* enable CCI */
/* if(dvbc.mode == 4) // 256QAM */
apb_write_reg(QAM_BASE + 0x54, 0xa25705fa);
/**/ cciflag = 1;
msleep(1000);
} else {
cciflag = 0;
}
dprintk("[cci][%s]--------------------------\n", __func__);
}
return 0;
}
int dvbc_get_cci_task(void)
{
if (cci_task)
return 0;
else
return 1;
}
void dvbc_create_cci_task(void)
{
int ret;
/*apb_write_reg(QAM_BASE+0xa8, 0x42b2ebe3); // enable CCI */
/* apb_write_reg(QAM_BASE+0xac, 0x42b2ebe3); // enable CCI */
/* if(dvbc.mode == 4) // 256QAM*/
/* apb_write_reg(QAM_BASE+0x54, 0xa25705fa); // */
ret = 0;
cci_task = kthread_create(dvbc_cci_task, NULL, "cci_task");
if (ret != 0) {
dprintk("[%s]Create cci kthread error!\n", __func__);
cci_task = NULL;
return;
}
wake_up_process(cci_task);
dprintk("[%s]Create cci kthread and wake up!\n", __func__);
}
void dvbc_kill_cci_task(void)
{
if (cci_task) {
kthread_stop(cci_task);
cci_task = NULL;
dprintk("[%s]kill cci kthread !\n", __func__);
}
}
u32 dvbc_set_qam_mode(unsigned char mode)
{
dprintk("auto change mode ,now mode is %d\n", mode);
apb_write_reg(QAM_BASE + 0x008, (mode & 7));
/* qam mode */
switch (mode) {
case 0: /* 16 QAM */
apb_write_reg(QAM_BASE + 0x054, 0x23460224);
/* EQ_FIR_CTL, */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
apb_write_reg(QAM_BASE + 0x074, 0x50001a0);
/* EQ_TH_LMS 40db 13db */
apb_write_reg(QAM_BASE + 0x07c, 0x003001e9);
/* EQ_NORM and EQ_TH_MMA */
/*apb_write_reg(QAM_BASE+0x080, 0x000be1ff);
* // EQ_TH_SMMA0
*/
apb_write_reg(QAM_BASE + 0x080, 0x000e01fe);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x00000000);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292b);
* // Pilips Tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292d);
* // Pilips Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092d);
/* Pilips Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66);
/* by raymond 20121213 */
break;
case 1: /* 32 QAM */
apb_write_reg(QAM_BASE + 0x054, 0x24560506);
/* EQ_FIR_CTL, */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x5000260);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x50001f0);
/* EQ_TH_LMS 40db 17.5db */
apb_write_reg(QAM_BASE + 0x07c, 0x00500102);
/* EQ_TH_MMA 0x000001cc */
apb_write_reg(QAM_BASE + 0x080, 0x00077140);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x001fb000);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292b);
* // Pilips Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092b);
/* Pilips Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66);
/* by raymond 20121213 */
break;
case 2: /* 64 QAM */
/*apb_write_reg(QAM_BASE+0x054, 0x2256033a);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0x2336043a);
/* EQ_FIR_CTL, by raymond */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x5000260);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000230);
/* EQ_TH_LMS 40db 17.5db */
apb_write_reg(QAM_BASE + 0x07c, 0x007001bd);
/* EQ_TH_MMA */
apb_write_reg(QAM_BASE + 0x080, 0x000580ed);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x001771fb);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d);
/* Pilips Tuner & maxlinear Tuner */
/*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a);
* // Pilips Tuner & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66);
/* by raymond 20121213 */
break;
case 3: /* 128 QAM */
/*apb_write_reg(QAM_BASE+0x054, 0x2557046a);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0x2437067a);
/* EQ_FIR_CTL, by raymond 20121213 */
apb_write_reg(QAM_BASE + 0x068, 0x00c000d0);
/* EQ_CRTH_SNR */
/* apb_write_reg(QAM_BASE+0x074, 0x02440240);
* // EQ_TH_LMS 18.5db 18db
*/
/* apb_write_reg(QAM_BASE+0x074, 0x04000400);
* // EQ_TH_LMS 22db 22.5db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000260);
/* EQ_TH_LMS 40db 19db */
/*apb_write_reg(QAM_BASE+0x07c, 0x00b000f2);
* // EQ_TH_MMA0x000000b2
*/
apb_write_reg(QAM_BASE + 0x07c, 0x00b00132);
/* EQ_TH_MMA0x000000b2 by raymond 20121213 */
apb_write_reg(QAM_BASE + 0x080, 0x0003a09d);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x000f8150);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x001a51f8);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092c);
/* Pilips Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66);
/* by raymond 20121213 */
break;
case 4: /* 256 QAM */
/*apb_write_reg(QAM_BASE+0x054, 0xa2580588);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0xa25905f9);
/* EQ_FIR_CTL, by raymond 20121213 */
apb_write_reg(QAM_BASE + 0x068, 0x01e00220);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x50002a0);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000270);
/* EQ_TH_LMS 40db 19db by raymond 201211213 */
apb_write_reg(QAM_BASE + 0x07c, 0x00f001a5);
/* EQ_TH_MMA */
apb_write_reg(QAM_BASE + 0x080, 0x0002c077);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x000bc0fe);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x0013f17e);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x01bc01f9);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips Tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292d);
* // Maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092d);
/* Maxlinear Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213, when adc=35M,sys=70M,
* its better than 0x61f2f66
*/
break;
default: /*64qam */
/*apb_write_reg(QAM_BASE+0x054, 0x2256033a);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0x2336043a);
/* EQ_FIR_CTL, by raymond */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x5000260);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000230);
/* EQ_TH_LMS 40db 17.5db */
apb_write_reg(QAM_BASE + 0x07c, 0x007001bd);
/* EQ_TH_MMA */
apb_write_reg(QAM_BASE + 0x080, 0x000580ed);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x001771fb);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d);
/* Pilips Tuner & maxlinear Tuner */
/*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a);
* // Pilips Tuner & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f66);
/* by raymond 20121213 */
break;
}
return 0;
}
u32 dvbc_get_status(void)
{
/* dprintk("c4 is %x\n",apb_read_reg(QAM_BASE+0xc4));*/
return apb_read_reg(QAM_BASE + 0xc4) & 0xf;
}
EXPORT_SYMBOL(dvbc_get_status);
static u32 dvbc_get_ch_power(void)
{
u32 tmp;
u32 ad_power;
u32 agc_gain;
u32 ch_power;
tmp = apb_read_reg(QAM_BASE + 0x09c);
ad_power = (tmp >> 22) & 0x1ff;
agc_gain = (tmp >> 0) & 0x7ff;
ad_power = ad_power >> 4;
/* ch_power = lookuptable(agc_gain) + ad_power; TODO */
ch_power = (ad_power & 0xffff) + ((agc_gain & 0xffff) << 16);
return ch_power;
}
static u32 dvbc_get_snr(void)
{
u32 tmp, snr;
tmp = apb_read_reg(QAM_BASE + 0x14) & 0xfff;
snr = tmp * 100 / 32; /* * 1e2 */
return snr;
}
static u32 dvbc_get_ber(void)
{
u32 rs_ber;
u32 rs_packet_len;
rs_packet_len = apb_read_reg(QAM_BASE + 0x10) & 0xffff;
rs_ber = apb_read_reg(QAM_BASE + 0x14) >> 12 & 0xfffff;
/* rs_ber = rs_ber / 204.0 / 8.0 / rs_packet_len; */
if (rs_packet_len == 0)
rs_ber = 1000000;
else
rs_ber = rs_ber * 613 / rs_packet_len; /* 1e-6 */
return rs_ber;
}
static u32 dvbc_get_per(void)
{
u32 rs_per;
u32 rs_packet_len;
u32 acc_rs_per_times;
rs_packet_len = apb_read_reg(QAM_BASE + 0x10) & 0xffff;
rs_per = apb_read_reg(QAM_BASE + 0x18) >> 16 & 0xffff;
acc_rs_per_times = apb_read_reg(QAM_BASE + 0xcc) & 0xffff;
/*rs_per = rs_per / rs_packet_len; */
if (rs_packet_len == 0)
rs_per = 10000;
else
rs_per = 10000 * rs_per / rs_packet_len; /* 1e-4 */
/*return rs_per; */
return acc_rs_per_times;
}
static u32 dvbc_get_symb_rate(void)
{
u32 tmp;
u32 adc_freq;
u32 symb_rate;
adc_freq = apb_read_reg(QAM_BASE + 0x34) >> 16 & 0xffff;
tmp = apb_read_reg(QAM_BASE + 0xb8);
if ((tmp >> 15) == 0)
symb_rate = 0;
else
symb_rate = 10 * (adc_freq << 12) / (tmp >> 15);
/* 1e4 */
return symb_rate;
}
static int dvbc_get_freq_off(void)
{
int tmp;
int symb_rate;
int freq_off;
symb_rate = dvbc_get_symb_rate();
tmp = apb_read_reg(QAM_BASE + 0xe0) & 0x3fffffff;
if (tmp >> 29 & 1)
tmp -= (1 << 30);
freq_off = ((tmp >> 16) * 25 * (symb_rate >> 10)) >> 3;
return freq_off;
}
static void dvbc_set_test_bus(u8 sel)
{
u32 tmp;
tmp = apb_read_reg(QAM_BASE + 0x08);
tmp &= ~(0x1f << 4);
tmp |= ((sel & 0x1f) << 4) | (1 << 3);
apb_write_reg(QAM_BASE + 0x08, tmp);
}
void dvbc_get_test_out(u8 sel, u32 len, u32 *buf)
{
int i, cnt;
dvbc_set_test_bus(sel);
for (i = 0, cnt = 0; i < len - 4 && cnt < 1000000; i++) {
buf[i] = apb_read_reg(QAM_BASE + 0xb0);
if (buf[i] >> 11 & 1) {
buf[i++] = apb_read_reg(QAM_BASE + 0xb0);
buf[i++] = apb_read_reg(QAM_BASE + 0xb0);
buf[i++] = apb_read_reg(QAM_BASE + 0xb0);
buf[i++] = apb_read_reg(QAM_BASE + 0xb0);
} else {
i--;
}
cnt++;
}
}
#if 0
static void dvbc_sw_reset(int addr, int idx)
{
u32 tmp;
tmp = apb_read_reg(QAM_BASE + addr);
tmp &= ~(1 << idx);
apb_write_reg(QAM_BASE + addr, tmp);
udelay(1);
tmp |= (1 << idx);
apb_write_reg(QAM_BASE + addr, tmp);
}
static void dvbc_reset(void)
{
dvbc_sw_reset(0x04, 0);
}
static void dvbc_eq_reset(void)
{
dvbc_sw_reset(0x50, 3);
}
static void dvbc_eq_smma_reset(void)
{
dvbc_sw_reset(0xe8, 0);
}
#endif
static void dvbc_reg_initial(struct aml_demod_sta *demod_sta)
{
u32 clk_freq;
u32 adc_freq;
u8 tuner;
u8 ch_mode;
u8 agc_mode;
u32 ch_freq;
u16 ch_if;
u16 ch_bw;
u16 symb_rate;
u32 phs_cfg;
int afifo_ctr;
int max_frq_off, tmp;
clk_freq = demod_sta->clk_freq; /* kHz */
adc_freq = demod_sta->adc_freq; /* kHz */
/* adc_freq = 25414;*/
tuner = demod_sta->tuner;
ch_mode = demod_sta->ch_mode;
agc_mode = demod_sta->agc_mode;
ch_freq = demod_sta->ch_freq; /* kHz */
ch_if = demod_sta->ch_if; /* kHz */
ch_bw = demod_sta->ch_bw; /* kHz */
symb_rate = demod_sta->symb_rate; /* k/sec */
dprintk("ch_if is %d, %d, %d, %d, %d\n",
ch_if, ch_mode, ch_freq, ch_bw, symb_rate);
/* ch_mode=4;*/
/* apb_write_reg(DEMOD_CFG_BASE,0x00000007);*/
/* disable irq */
apb_write_reg(QAM_BASE + 0xd0, 0);
/* reset */
/*dvbc_reset(); */
apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) & ~(1 << 4));
/* disable fsm_en */
apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) & ~(1 << 0));
/* Sw disable demod */
apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) | (1 << 0));
/* Sw enable demod */
apb_write_reg(QAM_BASE + 0x000, 0x00000000);
/* QAM_STATUS */
apb_write_reg(QAM_BASE + 0x004, 0x00000f00);
/* QAM_GCTL0 */
apb_write_reg(QAM_BASE + 0x008, (ch_mode & 7));
/* qam mode */
switch (ch_mode) {
case 0: /* 16 QAM */
apb_write_reg(QAM_BASE + 0x054, 0x23460224);
/* EQ_FIR_CTL, */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
apb_write_reg(QAM_BASE + 0x074, 0x50001a0);
/* EQ_TH_LMS 40db 13db */
apb_write_reg(QAM_BASE + 0x07c, 0x003001e9);
/* EQ_NORM and EQ_TH_MMA */
/*apb_write_reg(QAM_BASE+0x080, 0x000be1ff);
* // EQ_TH_SMMA0
*/
apb_write_reg(QAM_BASE + 0x080, 0x000e01fe);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x00000000);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292b);
* // Pilips Tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292d);
* // Pilips Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092d);
/* Pilips Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213 */
break;
case 1: /* 32 QAM */
apb_write_reg(QAM_BASE + 0x054, 0x24560506);
/* EQ_FIR_CTL, */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x5000260);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x50001f0);
/* EQ_TH_LMS 40db 17.5db */
apb_write_reg(QAM_BASE + 0x07c, 0x00500102);
/* EQ_TH_MMA 0x000001cc */
apb_write_reg(QAM_BASE + 0x080, 0x00077140);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x001fb000);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2b);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292b);
* // Pilips Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092b);
/* Pilips Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213 */
break;
case 2: /* 64 QAM */
/*apb_write_reg(QAM_BASE+0x054, 0x2256033a);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0x2336043a);
/* EQ_FIR_CTL, by raymond */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x5000260);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000230);
/* EQ_TH_LMS 40db 17.5db */
apb_write_reg(QAM_BASE + 0x07c, 0x007001bd);
/* EQ_TH_MMA */
apb_write_reg(QAM_BASE + 0x080, 0x000580ed);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x001771fb);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d);
/* Pilips Tuner & maxlinear Tuner */
/*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a);
* // Pilips Tuner & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213 */
break;
case 3: /* 128 QAM */
/*apb_write_reg(QAM_BASE+0x054, 0x2557046a);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0x2437067a);
/* EQ_FIR_CTL, by raymond 20121213 */
apb_write_reg(QAM_BASE + 0x068, 0x00c000d0);
/* EQ_CRTH_SNR */
/* apb_write_reg(QAM_BASE+0x074, 0x02440240);
* // EQ_TH_LMS 18.5db 18db
*/
/* apb_write_reg(QAM_BASE+0x074, 0x04000400);
* // EQ_TH_LMS 22db 22.5db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000260);
/* EQ_TH_LMS 40db 19db */
/*apb_write_reg(QAM_BASE+0x07c, 0x00b000f2);
* // EQ_TH_MMA0x000000b2
*/
apb_write_reg(QAM_BASE + 0x07c, 0x00b00132);
/* EQ_TH_MMA0x000000b2 by raymond 20121213 */
apb_write_reg(QAM_BASE + 0x080, 0x0003a09d);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x000f8150);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x001a51f8);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092c);
/* Pilips Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213 */
break;
case 4: /* 256 QAM */
/*apb_write_reg(QAM_BASE+0x054, 0xa2580588);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0xa25905f9);
/* EQ_FIR_CTL, by raymond 20121213 */
apb_write_reg(QAM_BASE + 0x068, 0x01e00220);
/* EQ_CRTH_SNR */
/*apb_write_reg(QAM_BASE+0x074, 0x50002a0);
* // EQ_TH_LMS 40db 19db
*/
apb_write_reg(QAM_BASE + 0x074, 0x5000270);
/* EQ_TH_LMS 40db 19db by raymond 201211213 */
apb_write_reg(QAM_BASE + 0x07c, 0x00f001a5);
/* EQ_TH_MMA */
apb_write_reg(QAM_BASE + 0x080, 0x0002c077);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x000bc0fe);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x0013f17e);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x01bc01f9);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips Tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292d);
* // Maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f80092d);
/* Maxlinear Tuner */
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213, when adc=35M,sys=70M,
* its better than 0x61f2f66
*/
break;
default: /*64qam */
/*apb_write_reg(QAM_BASE+0x054, 0x2256033a);
* // EQ_FIR_CTL,
*/
apb_write_reg(QAM_BASE + 0x054, 0x2336043a);
/* EQ_FIR_CTL, by raymond */
apb_write_reg(QAM_BASE + 0x068, 0x00c000c0);
/* EQ_CRTH_SNR */
/* EQ_TH_LMS 40db 19db */
apb_write_reg(QAM_BASE + 0x074, 0x5000230);
/* EQ_TH_LMS 40db 17.5db */
apb_write_reg(QAM_BASE + 0x07c, 0x007001bd);
/* EQ_TH_MMA */
apb_write_reg(QAM_BASE + 0x080, 0x000580ed);
/* EQ_TH_SMMA0 */
apb_write_reg(QAM_BASE + 0x084, 0x001771fb);
/* EQ_TH_SMMA1 */
apb_write_reg(QAM_BASE + 0x088, 0x00000000);
/* EQ_TH_SMMA2 */
apb_write_reg(QAM_BASE + 0x08c, 0x00000000);
/* EQ_TH_SMMA3 */
/*apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);
* // AGC_CTRL ALPS tuner
*/
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292c);
* // Pilips & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x094, 0x7f802b3d);
/* Pilips Tuner & maxlinear Tuner */
/*apb_write_reg(QAM_BASE+0x094, 0x7f802b3a);
* // Pilips Tuner & maxlinear Tuner
*/
apb_write_reg(QAM_BASE + 0x0c0, 0x061f2f67);
/* by raymond 20121213 */
break;
}
/*apb_write_reg(QAM_BASE+0x00c, 0xfffffffe);
* // adc_cnt, symb_cnt
*/
apb_write_reg(QAM_BASE + 0x00c, 0xffff8ffe);
/* adc_cnt, symb_cnt by raymond 20121213 */
if (clk_freq == 0)
afifo_ctr = 0;
else
afifo_ctr = (adc_freq * 256 / clk_freq) + 2;
if (afifo_ctr > 255)
afifo_ctr = 255;
apb_write_reg(QAM_BASE + 0x010, (afifo_ctr << 16) | 8000);
/* afifo, rs_cnt_cfg */
/*apb_write_reg(QAM_BASE+0x020, 0x21353e54);
* // PHS_reset & TIM_CTRO_ACCURATE sw_tim_select=0
*/
/*apb_write_reg(QAM_BASE+0x020, 0x21b53e54);
* //modified by qiancheng
*/
apb_write_reg(QAM_BASE + 0x020, 0x61b53e54);
/*modified by qiancheng by raymond 20121208 0x63b53e54 for cci */
/* apb_write_reg(QAM_BASE+0x020, 0x6192bfe2);
* //modifed by ligg 20130613 auto symb_rate scan
*/
if (adc_freq == 0)
phs_cfg = 0;
else
phs_cfg = (1 << 31) / adc_freq * ch_if / (1 << 8);
/* 8*fo/fs*2^20 fo=36.125, fs = 28.57114, = 21d775 */
/* dprintk("phs_cfg = %x\n", phs_cfg); */
apb_write_reg(QAM_BASE + 0x024, 0x4c000000 | (phs_cfg & 0x7fffff));
/* PHS_OFFSET, IF offset, */
if (adc_freq == 0) {
max_frq_off = 0;
} else {
max_frq_off = (1 << 29) / symb_rate;
/* max_frq_off = (400KHz * 2^29) /
* (AD=28571 * symbol_rate=6875)
*/
tmp = 40000000 / adc_freq;
max_frq_off = tmp * max_frq_off;
}
dprintk("max_frq_off is %x,\n", max_frq_off);
apb_write_reg(QAM_BASE + 0x02c, max_frq_off & 0x3fffffff);
/* max frequency offset, by raymond 20121208 */
/*apb_write_reg(QAM_BASE+0x030, 0x011bf400);
* // TIM_CTL0 start speed is 0, when know symbol rate
*/
apb_write_reg(QAM_BASE + 0x030, 0x245cf451);
/*MODIFIED BY QIANCHENG */
/* apb_write_reg(QAM_BASE+0x030, 0x245bf451);
* //modified by ligg 20130613 --auto symb_rate scan
*/
apb_write_reg(QAM_BASE + 0x034,
((adc_freq & 0xffff) << 16) | (symb_rate & 0xffff));
apb_write_reg(QAM_BASE + 0x038, 0x00400000);
/* TIM_SWEEP_RANGE 16000 */
/************* hw state machine config **********/
apb_write_reg(QAM_BASE + 0x040, 0x003c);
/* configure symbol rate step step 0*/
/* modified 0x44 0x48 */
apb_write_reg(QAM_BASE + 0x044, (symb_rate & 0xffff) * 256);
/* blind search, configure max symbol_rate for 7218 fb=3.6M */
/*apb_write_reg(QAM_BASE+0x048, 3600*256);
* // configure min symbol_rate fb = 6.95M
*/
apb_write_reg(QAM_BASE + 0x048, 3400 * 256);
/* configure min symbol_rate fb = 6.95M */
/*apb_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */
/*apb_write_reg(QAM_BASE+0x0c0, 0xffffff6f); // threshold */
/*apb_write_reg(QAM_BASE+0x0c0, 0xfffffd68); // threshold */
/*apb_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */
/*apb_write_reg(QAM_BASE+0x0c0, 0xffffff68); // threshold */
/*apb_write_reg(QAM_BASE+0x0c0, 0xffff2f67);
* // threshold for skyworth
*/
/* apb_write_reg(QAM_BASE+0x0c0, 0x061f2f67); // by raymond 20121208 */
/* apb_write_reg(QAM_BASE+0x0c0, 0x061f2f66);
* // by raymond 20121213, remove it to every constellation
*/
/************* hw state machine config **********/
apb_write_reg(QAM_BASE + 0x04c, 0x00008800); /* reserved */
/*apb_write_reg(QAM_BASE+0x050, 0x00000002); // EQ_CTL0 */
apb_write_reg(QAM_BASE + 0x050, 0x01472002);
/* EQ_CTL0 by raymond 20121208 */
/*apb_write_reg(QAM_BASE+0x058, 0xff550e1e); // EQ_FIR_INITPOS */
apb_write_reg(QAM_BASE + 0x058, 0xff100e1e);
/* EQ_FIR_INITPOS for skyworth */
apb_write_reg(QAM_BASE + 0x05c, 0x019a0000); /* EQ_FIR_INITVAL0 */
apb_write_reg(QAM_BASE + 0x060, 0x019a0000); /* EQ_FIR_INITVAL1 */
/*apb_write_reg(QAM_BASE+0x064, 0x01101128); // EQ_CRTH_TIMES */
apb_write_reg(QAM_BASE + 0x064, 0x010a1128);
/* EQ_CRTH_TIMES for skyworth */
apb_write_reg(QAM_BASE + 0x06c, 0x00041a05); /* EQ_CRTH_PPM */
apb_write_reg(QAM_BASE + 0x070, 0xffb9aa01); /* EQ_CRLP */
/*apb_write_reg(QAM_BASE+0x090, 0x00020bd5); // agc control */
apb_write_reg(QAM_BASE + 0x090, 0x00000bd5); /* agc control */
/* agc control */
/* apb_write_reg(QAM_BASE+0x094, 0x7f800d2c);// AGC_CTRL ALPS tuner */
/* apb_write_reg(QAM_BASE+0x094, 0x7f80292c); // Pilips Tuner */
if ((agc_mode & 1) == 0)
/* freeze if agc */
apb_write_reg(QAM_BASE + 0x094,
apb_read_reg(QAM_BASE + 0x94) | (0x1 << 10));
if ((agc_mode & 2) == 0) {
/* IF control */
/*freeze rf agc */
apb_write_reg(QAM_BASE + 0x094,
apb_read_reg(QAM_BASE + 0x94) | (0x1 << 13));
}
/*Maxlinear Tuner */
/*apb_write_reg(QAM_BASE+0x094, 0x7f80292d); */
apb_write_reg(QAM_BASE + 0x098, 0x9fcc8190);
/* AGC_IFGAIN_CTRL */
/*apb_write_reg(QAM_BASE+0x0a0, 0x0e028c00);
* // AGC_RFGAIN_CTRL 0x0e020800
*/
/*apb_write_reg(QAM_BASE+0x0a0, 0x0e03cc00);
* // AGC_RFGAIN_CTRL 0x0e020800
*/
/*apb_write_reg(QAM_BASE+0x0a0, 0x0e028700);
* // AGC_RFGAIN_CTRL 0x0e020800 now
*/
/*apb_write_reg(QAM_BASE+0x0a0, 0x0e03cd00);
* // AGC_RFGAIN_CTRL 0x0e020800
*/
/*apb_write_reg(QAM_BASE+0x0a0, 0x0603cd11);
* // AGC_RFGAIN_CTRL 0x0e020800 by raymond,
* if Adjcent channel test, maybe it need change.20121208 ad invert
*/
apb_write_reg(QAM_BASE + 0x0a0, 0x0603cd10);
/* AGC_RFGAIN_CTRL 0x0e020800 by raymond,
* if Adjcent channel test, maybe it need change.
* 20121208 ad invert,20130221, suit for two path channel.
*/
apb_write_reg(QAM_BASE + 0x004, apb_read_reg(QAM_BASE + 0x004) | 0x33);
/* IMQ, QAM Enable */
/* start hardware machine */
/*dvbc_sw_reset(0x004, 4); */
apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) | (1 << 4));
apb_write_reg(QAM_BASE + 0x0e8,
(apb_read_reg(QAM_BASE + 0x0e8) | (1 << 2)));
/* clear irq status */
apb_read_reg(QAM_BASE + 0xd4);
/* enable irq */
apb_write_reg(QAM_BASE + 0xd0, 0x7fff << 3);
/*auto track*/
/* dvbc_set_auto_symtrack(); */
}
u32 dvbc_set_auto_symtrack(void)
{
apb_write_reg(QAM_BASE + 0x030, 0x245bf45c); /*open track */
apb_write_reg(QAM_BASE + 0x020, 0x61b2bf5c);
apb_write_reg(QAM_BASE + 0x044, (7000 & 0xffff) * 256);
apb_write_reg(QAM_BASE + 0x038, 0x00220000);
apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) & ~(1 << 0));
/* Sw disable demod */
apb_write_reg(QAM_BASE + 0x4, apb_read_reg(QAM_BASE + 0x4) | (1 << 0));
/* Sw enable demod */
return 0;
}
int dvbc_set_ch(struct aml_demod_sta *demod_sta,
struct aml_demod_i2c *demod_i2c,
struct aml_demod_dvbc *demod_dvbc)
{
int ret = 0;
u16 symb_rate;
u8 mode;
u32 ch_freq;
dprintk("f=%d, s=%d, q=%d\n",
demod_dvbc->ch_freq, demod_dvbc->symb_rate, demod_dvbc->mode);
demod_i2c->tuner = 7;
mode = demod_dvbc->mode;
symb_rate = demod_dvbc->symb_rate;
ch_freq = demod_dvbc->ch_freq;
if (mode > 4) {
dprintk("Error: Invalid QAM mode option %d\n", mode);
mode = 2;
ret = -1;
}
if (symb_rate < 1000 || symb_rate > 7000) {
dprintk("Error: Invalid Symbol Rate option %d\n", symb_rate);
symb_rate = 6875;
ret = -1;
}
if (ch_freq < 1000 || ch_freq > 900000) {
dprintk("Error: Invalid Channel Freq option %d\n", ch_freq);
ch_freq = 474000;
ret = -1;
}
/* if (ret != 0) return ret; */
demod_sta->dvb_mode = 0;
demod_sta->ch_mode = mode;
/* 0:16, 1:32, 2:64, 3:128, 4:256 */
demod_sta->agc_mode = 1;
/* 0:NULL, 1:IF, 2:RF, 3:both */
demod_sta->ch_freq = ch_freq;
demod_sta->tuner = demod_i2c->tuner;
if (demod_i2c->tuner == 1)
demod_sta->ch_if = 36130; /* TODO DCT tuner */
else if (demod_i2c->tuner == 2)
demod_sta->ch_if = 4570; /* TODO Maxlinear tuner */
else if (demod_i2c->tuner == 7)
/* demod_sta->ch_if = 5000; // TODO Si2176 tuner */
demod_sta->ch_bw = 8000; /* TODO */
if (demod_sta->ch_if == 0)
demod_sta->ch_if = 5000;
demod_sta->symb_rate = symb_rate;
dvbc_reg_initial(demod_sta);
return ret;
}
int dvbc_status(struct aml_demod_sta *demod_sta,
struct aml_demod_i2c *demod_i2c,
struct aml_demod_sts *demod_sts)
{
struct aml_fe_dev *dev;
/* int ftmp, tmp; */
dev = NULL;
demod_sts->ch_sts = apb_read_reg(QAM_BASE + 0x18);
demod_sts->ch_pow = dvbc_get_ch_power();
demod_sts->ch_snr = dvbc_get_snr();
demod_sts->ch_ber = dvbc_get_ber();
demod_sts->ch_per = dvbc_get_per();
demod_sts->symb_rate = dvbc_get_symb_rate();
demod_sts->freq_off = dvbc_get_freq_off();
/*demod_sts->dat0 = apb_read_reg(QAM_BASE+0x28); */
/* demod_sts->dat0 = tuner_get_ch_power(demod_i2c);*/
demod_sts->dat1 = tuner_get_ch_power(dev);
#if 0
ftmp = demod_sts->ch_sts;
dprintk("[dvbc debug] ch_sts is %x\n", ftmp);
ftmp = demod_sts->ch_snr;
ftmp /= 100;
dprintk("snr %d dB ", ftmp);
ftmp = demod_sts->ch_ber;
dprintk("ber %.d ", ftmp);
tmp = demod_sts->ch_per;
dprintk("per %d ", tmp);
ftmp = demod_sts->symb_rate;
dprintk("srate %.d ", ftmp);
ftmp = demod_sts->freq_off;
dprintk("freqoff %.d kHz ", ftmp);
tmp = demod_sts->dat1;
dprintk("strength %ddb 0xe0 status is %lu ,b4 status is %lu", tmp,
(apb_read_reg(QAM_BASE + 0xe0) & 0xffff),
(apb_read_reg(QAM_BASE + 0xb4) & 0xffff));
dprintk("dagc_gain is %lu ", apb_read_reg(QAM_BASE + 0xa4) & 0x7f);
tmp = demod_sts->ch_pow;
dprintk("power is %ddb\n", (tmp & 0xffff));
#endif
return 0;
}
void dvbc_enable_irq(int dvbc_irq)
{
u32 mask;
/* clear status */
apb_read_reg(QAM_BASE + 0xd4);
/* enable irq */
mask = apb_read_reg(QAM_BASE + 0xd0);
mask |= (1 << dvbc_irq);
apb_write_reg(QAM_BASE + 0xd0, mask);
}
void dvbc_disable_irq(int dvbc_irq)
{
u32 mask;
/* disable irq */
mask = apb_read_reg(QAM_BASE + 0xd0);
mask &= ~(1 << dvbc_irq);
apb_write_reg(QAM_BASE + 0xd0, mask);
/* clear status */
apb_read_reg(QAM_BASE + 0xd4);
}
char *dvbc_irq_name[] = {
" ADC",
" Symbol",
" RS",
" In_Sync0",
" In_Sync1",
" In_Sync2",
" In_Sync3",
" In_Sync4",
"Out_Sync0",
"Out_Sync1",
"Out_Sync2",
"Out_Sync3",
"Out_Sync4",
"In_SyncCo",
"OutSyncCo",
" In_Dagc",
" Out_Dagc",
" Eq_Mode",
"RS_Uncorr"
};
void dvbc_isr(struct aml_demod_sta *demod_sta)
{
u32 stat, mask;
int dvbc_irq;
stat = apb_read_reg(QAM_BASE + 0xd4);
mask = apb_read_reg(QAM_BASE + 0xd0);
stat &= mask;
for (dvbc_irq = 0; dvbc_irq < 20; dvbc_irq++) {
if (stat >> dvbc_irq & 1) {
if (demod_sta->debug)
dprintk("irq: dvbc %2d %s %8x\n",
dvbc_irq, dvbc_irq_name[dvbc_irq],
stat);
/* dvbc_disable_irq(dvbc_irq); */
}
}
}
int dvbc_isr_islock(void)
{
#define IN_SYNC4_MASK (0x80)
u32 stat, mask;
stat = apb_read_reg(QAM_BASE + 0xd4);
apb_write_reg(QAM_BASE + 0xd4, 0);
mask = apb_read_reg(QAM_BASE + 0xd0);
stat &= mask;
return (stat & IN_SYNC4_MASK) == IN_SYNC4_MASK;
}