PD#165624: Add ATV NICAM.
Change-Id: I2bcc018cd5ff7a611baa2f5473cfa1dbce28118d
Signed-off-by: nengwen.chen <nengwen.chen@amlogic.com>
atvdemod_fe-objs = atvdemod_func.o atvauddemod_func.o atv_demod_v4l2.o atv_demod_driver.o atv_demod_ops.o atv_demod_debug.o
ccflags-y += -I.
-ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-core
\ No newline at end of file
DEBUGFS_CREATE_NODE(if_inv, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(ademod_debug_en, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(btsc_detect_delay, 0640, dentry, u32)\
+ DEBUGFS_CREATE_NODE(nicam_detect_delay, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(signal_audmode, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(audio_thd_threshold1, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(gde_curve, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(audio_gain_val, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(audio_a2_threshold, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(audio_a2_delay, 0640, dentry, u32)\
+ DEBUGFS_CREATE_NODE(audio_nicam_delay, 0640, dentry, u32)\
+ DEBUGFS_CREATE_NODE(audio_a2_auto, 0640, dentry, u32)\
+ DEBUGFS_CREATE_NODE(audio_a2_power_threshold, 0640, dentry, u32)\
}
#undef pr_dbg
#define pr_dbg(fmt, ...)\
do {\
- if (atvdemod_debug_en & 01)\
+ if (atvdemod_debug_en & 0x01)\
printk(fmt, ##__VA_ARGS__);\
} while (0)
#include "atvauddemod_func.h"
-#define AMLATVDEMOD_VER "Ref.2015/09/01a"
+#define AMLATVDEMOD_VER "V2.00"
struct aml_atvdemod_device *amlatvdemod_devp;
parm[n++] = token;
}
+ if (parm[0] == NULL)
+ goto EXIT;
+
if (!strncmp(parm[0], "init", 4)) {
ret = atv_demod_enter_mode();
if (ret)
retrieve_adc_power(&adc_power);
pr_info("adc_power:%d\n", adc_power);
- } else if (!strncmp(parm[0], "demod_set", 9)) {
-
} else if (!strncmp(parm[0], "mode_set", 8)) {
int priv_cfg = AML_ATVDEMOD_INIT;
struct dvb_frontend *fe = NULL;
- if (aml_atvdemod_dev == NULL)
- pr_info("aml_atvdemod_dev == NULL\n");
+ if (amlatvdemod_devp == NULL)
+ pr_info("amlatvdemod_devp == NULL\n");
- fe = &aml_atvdemod_dev->v4l2_fe.fe;
+ fe = &amlatvdemod_devp->v4l2_fe.fe;
- if (kstrtoul(parm[1], 10, &tmp) == 0)
+ if (parm[1] && kstrtoul(parm[1], 10, &tmp) == 0)
priv_cfg = tmp;
if (fe != NULL) {
pr_info("fe->ops.analog_ops.set_config == NULL\n");
} else
pr_info("fe == NULL\n");
+
+ pr_info("mode_set mode %d\n", priv_cfg);
+ } else if (!strncmp(parm[0], "params_set", 8)) {
+ struct dvb_frontend *fe = NULL;
+ struct analog_parameters params;
+ struct v4l2_analog_parameters *p = NULL;
+ unsigned int std = 0;
+
+ if (amlatvdemod_devp == NULL)
+ pr_info("amlatvdemod_devp == NULL\n");
+
+ fe = &amlatvdemod_devp->v4l2_fe.fe;
+ p = &amlatvdemod_devp->v4l2_fe.params;
+
+ if (fe != NULL && p != NULL) {
+ if (parm[1] && kstrtoul(parm[1], 0, &tmp) == 0)
+ std = tmp;
+ else
+ std = p->std;
+
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ params.audmode = p->audmode;
+ params.std = std;
+
+ if (fe->ops.analog_ops.set_params != NULL)
+ fe->ops.analog_ops.set_params(fe, ¶ms);
+ else
+ pr_info("fe->ops.analog_ops.set_params == NULL\n");
+ } else
+ pr_info("fe == NULL\n");
+
+ pr_info("params_set std 0x%x\n", std);
+ } else if (!strncmp(parm[0], "audio_set", 9)) {
+ int std = AUDIO_STANDARD_A2_K;
+
+ if (parm[1] && kstrtoul(parm[1], 10, &tmp) == 0)
+ std = tmp;
+
+ configure_adec(std);
+ adec_soft_reset();
+
+ pr_info("audio_set std %d\n", std);
+ } else if (!strncmp(parm[0], "atvdemod_status", 15)) {
+ struct v4l2_analog_parameters *p = NULL;
+
+ if (amlatvdemod_devp != NULL) {
+ p = &amlatvdemod_devp->v4l2_fe.params;
+ if (p != NULL) {
+ pr_info("[atvdemod] afc_range: %d\n",
+ p->afc_range);
+ pr_info("[atvdemod] frequency: %d\n",
+ p->frequency);
+ pr_info("[atvdemod] soundsys: %d\n",
+ p->soundsys);
+ pr_info("[atvdemod] std: 0x%x (%s %s)\n",
+ (unsigned int) amlatvdemod_devp->std,
+ v4l2_std_to_str(
+ (0xff000000 & amlatvdemod_devp->std)),
+ v4l2_std_to_str(
+ (0xffffff & amlatvdemod_devp->std)));
+ pr_info("[atvdemod] audmode: 0x%x\n",
+ amlatvdemod_devp->audmode);
+ pr_info("[atvdemod] flag: %d\n", p->flag);
+ pr_info("[atvdemod] tuner_id: %d\n",
+ amlatvdemod_devp->tuner_id);
+ pr_info("[atvdemod] if_freq: %d\n",
+ amlatvdemod_devp->if_freq);
+ pr_info("[atvdemod] if_inv: %d\n",
+ amlatvdemod_devp->if_inv);
+ pr_info("[atvdemod] fre_offset: %d\n",
+ amlatvdemod_devp->fre_offset);
+ pr_info("[atvdemod] version: %s.\n",
+ AMLATVDEMOD_VER);
+ }
+ }
} else
pr_dbg("invalid command\n");
+EXIT:
kfree(buf_orig);
return count;
pr_err("can't find tuner: %s.\n", str);
}
+ /* Get i2c adapter by i2c node */
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);
if (!pdev->i2c_adp)
pr_err("can't find tuner_i2c_adap.\n");
}
-#if 0
+#if 0 /* Get adapter by ID */
ret = of_property_read_u32(node, "tuner_i2c_ada_id", &val);
if (ret)
pr_err("can't find tuner_i2c_ada_id.\n");
struct dvb_frontend *fe = &v4l2_fe->fe;
if (!dev->analog_attached) {
- p = v4l2_attach(aml_atvdemod_attach, fe,
+ p = v4l2_attach(aml_atvdemod_attach, fe, v4l2_fe,
dev->i2c_adp, dev->i2c_addr, dev->tuner_id);
if (p != NULL)
dev->analog_attached = true;
pr_info("periphs_reg_base = 0x%p.\n", dev->periphs_reg_base);
+ /* add for audio system control */
+ dev->audio_demod_reg_base = ioremap(round_down(0xffd0d340, 0x3), 4);
+
+ pr_info("audio_demod_reg_base = 0x%p.\n", dev->audio_demod_reg_base);
+
aml_atvdemod_dt_parse(dev);
aml_attach_demod_tuner(dev);
return ret;
}
- pr_info("%s: OK.\n", __func__);
+ pr_info("%s: OK, atv demod version: %s.\n", __func__, AMLATVDEMOD_VER);
return 0;
}
void __iomem *audio_reg_base;
void __iomem *hiu_reg_base;
void __iomem *periphs_reg_base;
+ void __iomem *audio_demod_reg_base;
unsigned int reg_23cf; /* IIR filter */
int btsc_sap_mode; /*0: off 1:monitor 2:auto */
if ((vpll_lock == 0) && (line_lock == 0)) {
retrieve_vpll_carrier_audio_power(&power);
*state = 1;
- } else
+ } else {
*state = 0;
+ pr_audio("vpll_lock: 0x%x, line_lock: 0x%x\n",
+ vpll_lock, line_lock);
+ }
} else {
*state = 0;
pr_audio("%s, atv is not work, atv_state: %d.\n",
__func__, atv_state);
}
+
+ /* If the atv signal is locked, it means there is audio data,
+ * so no need to check the power value.
+ */
#if 0
if (power >= 150)
*state = 1;
amlatvdemod_devp->pin_name);
adc_set_pll_cntl(1, 0x1, NULL);
+ /* vdac_enable(1, 1); */
usleep_range(2000, 2100);
atvdemod_clk_init();
err_code = atvdemod_init();
amlatvdemod_devp->pin = NULL;
}
+ /* vdac_enable(0, 1); */
adc_set_pll_cntl(0, 0x1, NULL);
if (is_meson_txlx_cpu() || is_meson_txhd_cpu())
aud_demod_clk_gate(0);
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;
+ struct aml_atvdemod_parameters *p = &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;
+ p->param.frequency = params->frequency;
+ p->param.mode = params->mode;
+ p->param.audmode = params->audmode;
+ p->param.std = params->std;
/* afc tune disable,must cancel wq before set tuner freq*/
afc_timer_disable(fe);
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];
+ p->if_inv = if_info[0];
+ p->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) ||
- (atvdemod_param->tuner_id == AM_TUNER_SI2159)) {
+ if ((p->param.std != amlatvdemod_devp->std) ||
+ (p->tuner_id == AM_TUNER_R840) ||
+ (p->tuner_id == AM_TUNER_SI2151) ||
+ (p->tuner_id == AM_TUNER_MXL661) ||
+ (p->tuner_id == AM_TUNER_SI2159)) {
/* open AGC if needed */
if (amlatvdemod_devp->pin != NULL)
devm_pinctrl_put(amlatvdemod_devp->pin);
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;
+#if 0 /* unused */
+ last_frq = p->param.frequency;
+ last_std = p->param.std;
#endif
- if (amlatvdemod_devp->std != atvdemod_param->param.std ||
- amlatvdemod_devp->audmode != atvdemod_param->param.audmode ||
- amlatvdemod_devp->if_freq != atvdemod_param->if_freq ||
- amlatvdemod_devp->if_inv != atvdemod_param->if_inv ||
- amlatvdemod_devp->tuner_id != atvdemod_param->tuner_id) {
- amlatvdemod_devp->std = atvdemod_param->param.std;
- amlatvdemod_devp->audmode =
- atvdemod_param->param.audmode;
- amlatvdemod_devp->if_freq = atvdemod_param->if_freq;
- amlatvdemod_devp->if_inv = atvdemod_param->if_inv;
- amlatvdemod_devp->tuner_id = atvdemod_param->tuner_id;
+ if (amlatvdemod_devp->std != p->param.std ||
+ amlatvdemod_devp->audmode != p->param.audmode ||
+ amlatvdemod_devp->if_freq != p->if_freq ||
+ amlatvdemod_devp->if_inv != p->if_inv ||
+ amlatvdemod_devp->tuner_id != p->tuner_id) {
+ amlatvdemod_devp->std = p->param.std;
+ amlatvdemod_devp->audmode = p->param.audmode;
+ amlatvdemod_devp->if_freq = p->if_freq;
+ amlatvdemod_devp->if_inv = p->if_inv;
+ amlatvdemod_devp->tuner_id = p->tuner_id;
+
atv_dmd_set_std();
- } else {
+
+ } else
atv_dmd_soft_reset();
- return;
- }
if (!atv_demod_get_scan_mode())
atvauddemod_init();
-
- pr_info("[%s] set std color %s, audio type %s.\n",
- __func__,
- v4l2_std_to_str((0xff000000 & amlatvdemod_devp->std)),
- v4l2_std_to_str((0xffffff & amlatvdemod_devp->std)));
- pr_info("[%s] set if_freq %d, if_inv %d.\n",
- __func__, amlatvdemod_devp->if_freq,
- amlatvdemod_devp->if_inv);
}
/* afc tune enable */
/* analog_search_flag == 0 or afc_range != 0 means searching */
if ((fe->ops.info.type == FE_ANALOG)
&& (atv_demod_get_scan_mode() == 0)
- && (atvdemod_param->param.mode == 0))
+ && (p->param.mode == 0))
afc_timer_enable(fe);
}
/* add line lock status for atv scan */
retrieve_vpll_carrier_line_lock(&line_lock);
- if ((vpll_lock & 0x1) == 0 && line_lock == 0) {
+ if (vpll_lock == 0 && line_lock == 0) {
*signal = V4L2_HAS_LOCK;
- pr_info("visual carrier lock:locked\n");
+ pr_info("%s locked [vpll_lock: 0x%x, line_lock:0x%x]\n",
+ __func__, vpll_lock, line_lock);
} else {
*signal = V4L2_TIMEDOUT;
- pr_info("visual carrier lock:unlocked\n");
+ pr_info("%s unlocked [vpll_lock: 0x%x, line_lock:0x%x]\n",
+ __func__, vpll_lock, line_lock);
}
return 0;
mutex_unlock(&atv_demod_list_mutex);
- pr_info("%s: OK.\n", __func__);
-
return 0;
}
.i2c_gate_ctrl = NULL,
};
+
+unsigned int tuner_status_cnt = 8; /* 4-->16 test on sky mxl661 */
+
+bool slow_mode;
+
+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_info("%s: OK.\n", __func__);
+}
+EXPORT_SYMBOL(aml_fe_hook_cvd);
+
+static v4l2_std_id atvdemod_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 atvdemod_fe_tvin_fmt_to_v4l2_std(int fmt)
+{
+ v4l2_std_id std = 0;
+
+ switch (fmt) {
+ case TVIN_SIG_FMT_CVBS_NTSC_M:
+ std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M;
+ break;
+ case TVIN_SIG_FMT_CVBS_NTSC_443:
+ std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_443;
+ break;
+ case TVIN_SIG_FMT_CVBS_NTSC_50:
+ std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M;
+ break;
+ case TVIN_SIG_FMT_CVBS_PAL_I:
+ std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_I;
+ break;
+ case TVIN_SIG_FMT_CVBS_PAL_M:
+ std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M;
+ break;
+ case TVIN_SIG_FMT_CVBS_PAL_60:
+ std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_60;
+ break;
+ case TVIN_SIG_FMT_CVBS_PAL_CN:
+ std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_Nc;
+ break;
+ case TVIN_SIG_FMT_CVBS_SECAM:
+ std = V4L2_COLOR_STD_SECAM | V4L2_STD_SECAM_L;
+ break;
+ default:
+ pr_err("%s: Unsupport fmt: 0x%x\n", __func__, fmt);
+ break;
+ }
+
+ return std;
+}
+
+static void atvdemod_fe_try_analog_format(struct v4l2_frontend *v4l2_fe,
+ int auto_search_std, v4l2_std_id *video_fmt,
+ unsigned int *audio_fmt)
+{
+ struct dvb_frontend *fe = &v4l2_fe->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;
+ unsigned int audio = 0;
+
+ if (auto_search_std & 0x01) {
+ 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->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_COLOR_STD_PAL)
+ p->std = V4L2_COLOR_STD_NTSC
+ | V4L2_STD_NTSC_M;
+#if 0 /*for secam */
+ else if (p->std & V4L2_COLOR_STD_NTSC)
+ p->std = V4L2_COLOR_STD_SECAM
+ | V4L2_STD_SECAM;
+#endif
+ else if (p->std & V4L2_COLOR_STD_NTSC)
+ p->std = V4L2_COLOR_STD_PAL
+ | V4L2_STD_PAL_DK;
+
+ p->frequency += 1;
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ 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 video fmt, assume PAL.\n",
+ __func__);
+ std_bk = TVIN_SIG_FMT_CVBS_PAL_I;
+ p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_DK;
+ p->frequency += 1;
+ p->audmode = V4L2_STD_PAL_DK;
+
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ 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 = atvdemod_fe_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 (!(auto_search_std & 0x02)) {
+ *audio_fmt = p->audmode;
+ return;
+ }
+
+ if (std_bk & V4L2_COLOR_STD_NTSC) {
+#if 1 /* For TV Signal Generator(TG39) test, NTSC need support other audio.*/
+ amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK);
+ audio = aml_audiomode_autodet(fe);
+ pr_info("autodet audmode 0x%x\n", audio);
+ audio = atvdemod_fmt_2_v4l2_std(audio);
+ pr_info("v4l2_std audmode 0x%x\n", audio);
+#if 0 /* I don't know what's going on here */
+ 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;
+ *video_fmt |= V4L2_STD_NTSC_M;
+#endif
+ } else if (std_bk & V4L2_COLOR_STD_SECAM) {
+#if 1 /* For support SECAM-DK/BG/I/L */
+ amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L);
+ audio = aml_audiomode_autodet(fe);
+ pr_info("autodet audmode 0x%x\n", audio);
+ audio = atvdemod_fmt_2_v4l2_std(audio);
+ pr_info("v4l2_std audmode 0x%x\n", audio);
+#else
+ audio = V4L2_STD_SECAM_L;
+#endif
+ } else {
+ /*V4L2_COLOR_STD_PAL*/
+ amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK);
+ audio = aml_audiomode_autodet(fe);
+ pr_info("autodet audmode 0x%x\n", audio);
+ audio = atvdemod_fmt_2_v4l2_std(audio);
+ pr_info("v4l2_std audmode 0x%x\n", audio);
+#if 0 /* Why do this to me? We need support PAL_M.*/
+ if (audio == V4L2_STD_PAL_M) {
+ audio = atvdemod_fmt_2_v4l2_std(broad_std_except_pal_m);
+ pr_info("select audmode 0x%x\n", audio);
+ }
+#endif
+ }
+
+ *audio_fmt = audio;
+}
+
+static int atvdemod_fe_afc_closer(struct v4l2_frontend *v4l2_fe, int minafcfreq,
+ int maxafcfreq, int isAutoSearch)
+{
+ struct dvb_frontend *fe = &v4l2_fe->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;
+ unsigned int tuner_id = v4l2_fe->tuner_id;
+
+ 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);
+ 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 (tuner_id == AM_TUNER_SI2151 ||
+ tuner_id == AM_TUNER_SI2159 ||
+ tuner_id == AM_TUNER_R840)
+ usleep_range(20 * 1000, 20 * 1000 + 100);
+ else if (tuner_id == AM_TUNER_MXL661)
+ usleep_range(30 * 1000, 30 * 1000 + 100);
+
+ if (fe->ops.analog_ops.get_afc &&
+ ((tuner_id == AM_TUNER_R840) ||
+ (tuner_id == AM_TUNER_SI2151) ||
+ (tuner_id == AM_TUNER_SI2159) ||
+ (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);
+
+ pr_dbg("[%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->afc_range;
+ 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);
+ pr_dbg("[%s] get afc %d khz done, freq %u.\n",
+ __func__, afc, p->frequency);
+ }
+
+ return 0;
+}
+
+static int atvdemod_fe_set_property(struct v4l2_frontend *v4l2_fe,
+ struct v4l2_property *tvp)
+{
+ struct dvb_frontend *fe = &amlatvdemod_devp->v4l2_fe.fe;
+ struct atv_demod_priv *priv = fe->analog_demod_priv;
+
+ pr_dbg("%s: cmd = 0x%x.\n", __func__, tvp->cmd);
+
+ switch (tvp->cmd) {
+ case V4L2_SOUND_SYS:
+ aud_mode = tvp->data & 0xFF;
+ priv->sound_sys.output_mode = tvp->data & 0xFF;
+ break;
+
+ case V4L2_SLOW_SEARCH_MODE:
+ tvp->data = slow_mode;
+ break;
+
+ default:
+ pr_dbg("%s: property %d doesn't exist\n",
+ __func__, tvp->cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int atvdemod_fe_get_property(struct v4l2_frontend *v4l2_fe,
+ struct v4l2_property *tvp)
+{
+ pr_dbg("%s: cmd = 0x%x.\n", __func__, tvp->cmd);
+
+ switch (tvp->cmd) {
+ case V4L2_SOUND_SYS:
+ tvp->data = ((aud_std & 0xFF) << 16)
+ | ((signal_audmode & 0xFF) << 8)
+ | (aud_mode & 0xFF);
+ break;
+
+ case V4L2_SLOW_SEARCH_MODE:
+ slow_mode = tvp->data;
+ break;
+
+ default:
+ pr_dbg("%s: property %d doesn't exist\n",
+ __func__, tvp->cmd);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static enum v4l2_search atvdemod_fe_search(struct v4l2_frontend *v4l2_fe)
+{
+ struct analog_parameters params;
+ struct dvb_frontend *fe = &v4l2_fe->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;
+ unsigned int audio = 0;
+ int double_check_cnt = 1;
+ int auto_search_std = 0;
+ int search_count = 0;
+ bool try_secam = false;
+ int ret = -1;
+ unsigned int tuner_id = v4l2_fe->tuner_id;
+ int priv_cfg = 0;
+
+ if (unlikely(!fe || !p ||
+ !fe->ops.tuner_ops.get_status ||
+ !fe->ops.analog_ops.has_signal ||
+ !fe->ops.analog_ops.set_params ||
+ !fe->ops.analog_ops.set_config)) {
+ 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_info("[%s] afc_range: [%d], tuner: [%d], freq: [%d], flag: [%d].\n",
+ __func__, p->afc_range, tuner_id,
+ p->frequency, p->flag);
+
+ /* 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_COLOR_STD_NTSC | V4L2_STD_NTSC_M;
+ auto_search_std = 0x01;
+ pr_dbg("[%s] user std is 0, so set it to NTSC | M.\n",
+ __func__);
+ }
+
+ if (p->audmode == 0) {
+ if (auto_search_std)
+ p->audmode = p->std & 0x00FFFFFF;
+ else {
+ if (p->std & V4L2_COLOR_STD_PAL)
+ p->audmode = V4L2_STD_PAL_DK;
+ else if (p->std & V4L2_COLOR_STD_NTSC)
+ p->audmode = V4L2_STD_NTSC_M;
+ else if (p->std & V4L2_COLOR_STD_SECAM)
+ p->audmode = V4L2_STD_PAL_DK;
+
+ p->std = (p->std & 0xFF000000) | p->audmode;
+ }
+ auto_search_std |= 0x02;
+ pr_dbg("[%s] user audmode is 0, so set it to %s.\n",
+ __func__, v4l2_std_to_str(p->audmode));
+ }
+
+ priv_cfg = AML_ATVDEMOD_SCAN_MODE;
+ fe->ops.analog_ops.set_config(fe, &priv_cfg);
+
+ /*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 || (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 std: 0x%08x, audmode: 0x%08x\n",
+ __func__, (unsigned int) p->std, p->audmode);
+
+ while (minafcfreq <= p->frequency &&
+ p->frequency <= maxafcfreq) {
+
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ 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 (tuner_id == AM_TUNER_MXL661) {
+ usleep_range(30 * 1000, 30 * 1000 + 100);
+ } else if (tuner_id == AM_TUNER_R840) {
+ usleep_range(20 * 1000, 20 * 1000 + 100);
+ fe->ops.tuner_ops.get_status(fe,
+ &tuner_state);
+ } else {
+ /* AM_TUNER_SI2151 and AM_TUNER_SI2159 */
+ 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) &&
+ (tuner_id != AM_TUNER_R840)) ||
+ ((ade_state == V4L2_HAS_LOCK &&
+ tuner_state == V4L2_HAS_LOCK) &&
+ (tuner_id == AM_TUNER_R840))) {
+ pll_lock = true;
+ break;
+ }
+
+ if (tuner_status_cnt_local == 0) {
+ if (auto_search_std &&
+ try_secam == false &&
+ !(p->std & V4L2_COLOR_STD_SECAM) &&
+ !(p->std & V4L2_STD_SECAM_L)) {
+ /* backup the std and audio mode */
+ std_bk = p->std;
+ audio = p->audmode;
+
+ p->std = (V4L2_COLOR_STD_SECAM
+ | V4L2_STD_SECAM_L);
+ p->audmode = V4L2_STD_SECAM_L;
+
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ params.audmode = p->audmode;
+ params.std = p->std;
+ fe->ops.analog_ops.set_params(fe,
+ ¶ms);
+
+ try_secam = true;
+
+ tuner_status_cnt_local =
+ tuner_status_cnt / 2;
+
+ continue;
+ }
+
+ if (try_secam) {
+ p->std = std_bk;
+ p->audmode = audio;
+
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ params.audmode = p->audmode;
+ params.std = p->std;
+ fe->ops.analog_ops.set_params(fe,
+ ¶ms);
+
+ try_secam = false;
+ }
+
+ break;
+ }
+ } while (1);
+
+ std_bk = 0;
+ audio = 0;
+
+ 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 = atvdemod_fe_afc_closer(v4l2_fe, minafcfreq,
+ maxafcfreq + ATV_AFC_500KHZ, 1);
+ if (ret == 0) {
+ atvdemod_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;
+ audio = 0;
+ }
+
+ /* sync param */
+ /* aml_fe_analog_sync_frontend(fe); */
+ priv_cfg = AML_ATVDEMOD_UNSCAN_MODE;
+ fe->ops.analog_ops.set_config(fe, &priv_cfg);
+ return V4L2_SEARCH_SUCCESS;
+ }
+ }
+
+ /*avoid sound format is not match after search over */
+ if (std_bk != 0 && audio != 0) {
+ p->std = std_bk;
+ p->audmode = audio;
+
+ params.frequency = p->frequency;
+ params.mode = p->afc_range;
+ params.audmode = p->audmode;
+ params.std = p->std;
+
+ fe->ops.analog_ops.set_params(fe, ¶ms);
+ std_bk = 0;
+ audio = 0;
+ }
+
+ pr_dbg("[%s] freq[analog.std:0x%08x] is[%d] unlock\n",
+ __func__,
+ (uint32_t) p->std, p->frequency);
+
+ if (p->frequency >= 44200000 &&
+ p->frequency <= 44300000 &&
+ double_check_cnt) {
+ double_check_cnt--;
+ pr_err("%s 44.25Mhz double check\n", __func__);
+ } else {
+ ++search_count;
+ p->frequency += afc_step * ((search_count % 2) ?
+ -search_count : search_count);
+ }
+ }
+
+ pr_dbg("[%s] [%d] over of range [min=%d, max=%d], search failed.\n",
+ __func__, p->frequency, minafcfreq, maxafcfreq);
+ p->frequency = set_freq;
+
+ priv_cfg = AML_ATVDEMOD_UNSCAN_MODE;
+ fe->ops.analog_ops.set_config(fe, &priv_cfg);
+
+ return DVBFE_ALGO_SEARCH_FAILED;
+}
+
+static struct v4l2_frontend_ops atvdemod_fe_ops = {
+ .set_property = atvdemod_fe_set_property,
+ .get_property = atvdemod_fe_get_property,
+ .search = atvdemod_fe_search,
+};
+
struct dvb_frontend *aml_atvdemod_attach(struct dvb_frontend *fe,
+ struct v4l2_frontend *v4l2_fe,
struct i2c_adapter *i2c_adap, u8 i2c_addr, u32 tuner_id)
{
int instance = 0;
memcpy(&fe->ops.analog_ops, &atvdemod_ops,
sizeof(struct analog_demod_ops));
+ memcpy(&v4l2_fe->ops, &atvdemod_fe_ops,
+ sizeof(struct v4l2_frontend_ops));
+
return fe;
}
EXPORT_SYMBOL(aml_atvdemod_attach);
#include "atv_demod_driver.h"
+struct atv_demod_sound_system {
+ unsigned int broadcast_std;
+ unsigned int audio_std;
+ unsigned int input_mode;
+ unsigned int output_mode;
+};
+
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;
+ struct atv_demod_sound_system sound_sys;
struct work_struct demod_wq;
};
extern int atv_demod_enter_mode(void);
struct dvb_frontend *aml_atvdemod_attach(struct dvb_frontend *fe,
+ struct v4l2_frontend *v4l2_fe,
struct i2c_adapter *i2c_adap, u8 i2c_addr, u32 tuner_id);
+
#endif /* __ATV_DEMOD_OPS_H__ */
static DEFINE_MUTEX(v4l2_fe_mutex);
/* static int v4l2_shutdown_timeout;*/
-unsigned int tuner_status_cnt = 8; /* 4-->16 test on sky mxl661 */
-
-bool slow_mode;
-
-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_info("%s: OK.\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_COLOR_STD_NTSC | V4L2_STD_NTSC_M;
- break;
- case TVIN_SIG_FMT_CVBS_NTSC_443:
- std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_443;
- break;
- case TVIN_SIG_FMT_CVBS_NTSC_50:
- std = V4L2_COLOR_STD_NTSC | V4L2_STD_NTSC_M;
- break;
- case TVIN_SIG_FMT_CVBS_PAL_I:
- std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_I;
- break;
- case TVIN_SIG_FMT_CVBS_PAL_M:
- std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_M;
- break;
- case TVIN_SIG_FMT_CVBS_PAL_60:
- std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_60;
- break;
- case TVIN_SIG_FMT_CVBS_PAL_CN:
- std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_Nc;
- break;
- case TVIN_SIG_FMT_CVBS_SECAM:
- std = V4L2_COLOR_STD_SECAM | V4L2_STD_SECAM_L;
- break;
- default:
- pr_err("%s: Unsupport fmt: 0x%x\n", __func__, fmt);
- break;
- }
-
- return std;
-}
-
-static void v4l2_fe_try_analog_format(struct v4l2_frontend *v4l2_fe,
- int auto_search_std, v4l2_std_id *video_fmt,
- unsigned int *audio_fmt)
-{
- struct dvb_frontend *fe = &v4l2_fe->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;
- unsigned int audio = 0;
-
- if (auto_search_std & 0x01) {
- 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->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_COLOR_STD_PAL)
- p->std = V4L2_COLOR_STD_NTSC
- | V4L2_STD_NTSC_M;
-/*
- else if (p->std & V4L2_COLOR_STD_NTSC)
- p->std = V4L2_COLOR_STD_SECAM
- | V4L2_STD_SECAM;
-*/
- else if (p->std & V4L2_COLOR_STD_NTSC)
- p->std = V4L2_COLOR_STD_PAL
- | V4L2_STD_PAL_DK;
-
- p->frequency += 1;
- params.frequency = p->frequency;
- params.mode = p->afc_range;
- 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 video fmt, assume PAL.\n",
- __func__);
- std_bk = TVIN_SIG_FMT_CVBS_PAL_I;
- p->std = V4L2_COLOR_STD_PAL | V4L2_STD_PAL_DK;
- p->frequency += 1;
- p->audmode = V4L2_STD_PAL_DK;
-
- params.frequency = p->frequency;
- params.mode = p->afc_range;
- 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 (!(auto_search_std & 0x02)) {
- *audio_fmt = p->audmode;
- return;
- }
-
- if (std_bk & V4L2_COLOR_STD_NTSC) {
-#if 1 /* For TV Signal Generator(TG39) test, NTSC need support other audio.*/
- amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK);
- audio = aml_audiomode_autodet(fe);
- pr_info("autodet audmode 0x%x\n", audio);
- audio = demod_fmt_2_v4l2_std(audio);
- pr_info("v4l2_std audmode 0x%x\n", 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;
- *video_fmt |= V4L2_STD_NTSC_M;
-#endif
- } else if (std_bk & V4L2_COLOR_STD_SECAM) {
-#if 1 /* For support SECAM-DK/BG/I/L */
- amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_SECAM_L);
- audio = aml_audiomode_autodet(fe);
- pr_info("autodet audmode 0x%x\n", audio);
- audio = demod_fmt_2_v4l2_std(audio);
- pr_info("v4l2_std audmode 0x%x\n", audio);
-#else
- audio = V4L2_STD_SECAM_L;
-#endif
- } else {
- /*V4L2_COLOR_STD_PAL*/
- amlatvdemod_set_std(AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK);
- audio = aml_audiomode_autodet(fe);
- pr_info("autodet audmode 0x%x\n", audio);
- audio = demod_fmt_2_v4l2_std(audio);
- pr_info("v4l2_std audmode 0x%x\n", 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_info("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->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;
- unsigned int tuner_id = v4l2_fe->tuner_id;
-
- 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);
- 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 (tuner_id == AM_TUNER_SI2151 ||
- tuner_id == AM_TUNER_SI2159 ||
- tuner_id == AM_TUNER_R840)
- usleep_range(20 * 1000, 20 * 1000 + 100);
- else if (tuner_id == AM_TUNER_MXL661)
- usleep_range(30 * 1000, 30 * 1000 + 100);
-
- if (fe->ops.analog_ops.get_afc &&
- ((tuner_id == AM_TUNER_R840) ||
- (tuner_id == AM_TUNER_SI2151) ||
- (tuner_id == AM_TUNER_SI2159) ||
- (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);
-
- pr_dbg("[%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->afc_range;
- 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);
- pr_dbg("[%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->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;
- unsigned int audio = 0;
- int double_check_cnt = 1;
- int auto_search_std = 0;
- int search_count = 0;
- bool try_secam = false;
- int ret = -1;
- unsigned int tuner_id = v4l2_fe->tuner_id;
- int priv_cfg = 0;
-
-#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 ||
- !fe->ops.analog_ops.set_params ||
- !fe->ops.analog_ops.set_config)) {
- 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_info("[%s] afc_range: [%d], tuner: [%d], freq: [%d], flag: [%d].\n",
- __func__, p->afc_range, tuner_id,
- p->frequency, p->flag);
-
- /* 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_COLOR_STD_NTSC | V4L2_STD_NTSC_M;
- auto_search_std = 0x01;
- pr_dbg("[%s] user std is 0, so set it to NTSC | M.\n",
- __func__);
- }
-
- if (p->audmode == 0) {
- if (auto_search_std)
- p->audmode = p->std & 0x00FFFFFF;
- else {
- if (p->std & V4L2_COLOR_STD_PAL)
- p->audmode = V4L2_STD_PAL_DK;
- else if (p->std & V4L2_COLOR_STD_NTSC)
- p->audmode = V4L2_STD_NTSC_M;
- else if (p->std & V4L2_COLOR_STD_SECAM)
- p->audmode = V4L2_STD_PAL_DK;
-
- p->std = (p->std & 0xFF000000) | p->audmode;
- }
- auto_search_std |= 0x02;
- pr_dbg("[%s] user audmode is 0, so set it to %s.\n",
- __func__, v4l2_std_to_str(p->audmode));
- }
-
- priv_cfg = AML_ATVDEMOD_SCAN_MODE;
- fe->ops.analog_ops.set_config(fe, &priv_cfg);
-
- /*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 || (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 std: 0x%08x, audmode: 0x%08x\n",
- __func__, (unsigned int) p->std, p->audmode);
-
-#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) {
-
- params.frequency = p->frequency;
- params.mode = p->afc_range;
- 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 (tuner_id == AM_TUNER_MXL661) {
- usleep_range(30 * 1000, 30 * 1000 + 100);
- } else if (tuner_id == AM_TUNER_R840) {
- usleep_range(20 * 1000, 20 * 1000 + 100);
- fe->ops.tuner_ops.get_status(fe,
- &tuner_state);
- } else {
- /* AM_TUNER_SI2151 and AM_TUNER_SI2159 */
- 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) &&
- (tuner_id != AM_TUNER_R840)) ||
- ((ade_state == V4L2_HAS_LOCK &&
- tuner_state == V4L2_HAS_LOCK) &&
- (tuner_id == AM_TUNER_R840))) {
- pll_lock = true;
- break;
- }
-
- if (tuner_status_cnt_local == 0) {
- if (auto_search_std &&
- !(p->std & V4L2_COLOR_STD_SECAM) &&
- !(p->std & V4L2_STD_SECAM_L)) {
- /* backup the std and audio mode */
- std_bk = p->std;
- audio = p->audmode;
-
- p->std = (V4L2_COLOR_STD_SECAM
- | V4L2_STD_SECAM_L);
- p->audmode = V4L2_STD_SECAM_L;
-
- params.frequency = p->frequency;
- params.mode = p->afc_range;
- params.audmode = p->audmode;
- params.std = p->std;
- fe->ops.analog_ops.set_params(fe,
- ¶ms);
-
- try_secam = true;
-
- tuner_status_cnt_local =
- tuner_status_cnt / 2;
-
- continue;
- }
-
- if (try_secam) {
- p->std = std_bk;
- p->audmode = audio;
-
- params.frequency = p->frequency;
- params.mode = p->afc_range;
- params.audmode = p->audmode;
- params.std = p->std;
- fe->ops.analog_ops.set_params(fe,
- ¶ms);
-
- try_secam = false;
- }
-
- break;
- }
- } while (1);
-
- std_bk = 0;
- audio = 0;
-
- 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;
- audio = 0;
- }
-#ifdef DEBUG_TIME_CUS
- time_end = jiffies_to_msecs(jiffies);
- time_delta = time_end - time_start;
- pr_dbg("[%s] time_delta:%d ms\n",
- __func__, time_delta);
-#endif
- /* sync param */
- /* aml_fe_analog_sync_frontend(fe); */
- priv_cfg = AML_ATVDEMOD_UNSCAN_MODE;
- fe->ops.analog_ops.set_config(fe, &priv_cfg);
- return V4L2_SEARCH_SUCCESS;
- }
- }
-
- /*avoid sound format is not match after search over */
- if (std_bk != 0 && audio != 0) {
- p->std = std_bk;
- p->audmode = audio;
-
- params.frequency = p->frequency;
- params.mode = p->afc_range;
- params.audmode = p->audmode;
- params.std = p->std;
-
- fe->ops.analog_ops.set_params(fe, ¶ms);
- std_bk = 0;
- audio = 0;
- }
-
- pr_dbg("[%s] freq[analog.std:0x%08x] is[%d] unlock\n",
- __func__,
- (uint32_t) p->std, p->frequency);
-
- 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 {
- ++search_count;
- 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("[%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("[%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;
-
- priv_cfg = AML_ATVDEMOD_UNSCAN_MODE;
- fe->ops.analog_ops.set_config(fe, &priv_cfg);
-
- return DVBFE_ALGO_SEARCH_FAILED;
-}
-
static int v4l2_frontend_get_event(struct v4l2_frontend *v4l2_fe,
struct v4l2_frontend_event *event, int flags)
*/
if ((fepriv->algo_status & V4L2_SEARCH_AGAIN)
&& !(fepriv->state & V4L2FE_STATE_IDLE)) {
- if (v4l2_fe->search) {
- fepriv->algo_status = v4l2_fe->search(v4l2_fe);
+ if (v4l2_fe->ops.search) {
+ fepriv->algo_status =
+ v4l2_fe->ops.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.
switch (tvp->cmd) {
case V4L2_TUNE:
break;
- case V4L2_NICAM:
+ case V4L2_SOUND_SYS:
+ case V4L2_SLOW_SEARCH_MODE:
+ /* Allow the frontend to override outgoing properties */
+ if (v4l2_fe->ops.set_property) {
+ r = v4l2_fe->ops.set_property(v4l2_fe, tvp);
+ if (r < 0)
+ return r;
+ }
break;
default:
return -EINVAL;
static int v4l2_property_process_get(struct v4l2_frontend *v4l2_fe,
struct v4l2_property *tvp, struct file *file)
{
+ int r = 0;
+
switch (tvp->cmd) {
- case V4L2_NICAM:
- tvp->u.data = 0;
+ case V4L2_SOUND_SYS:
+ case V4L2_SLOW_SEARCH_MODE:
+ /* Allow the frontend to override outgoing properties */
+ if (v4l2_fe->ops.get_property) {
+ r = v4l2_fe->ops.get_property(v4l2_fe, tvp);
+ if (r < 0)
+ return r;
+ }
break;
default:
struct v4l2_property *tvp = NULL;
int i = 0;
- pr_dbg("%s.\n", __func__);
+ pr_dbg("%s: cmd = 0x%x.\n", __func__, cmd);
if (cmd == V4L2_SET_PROPERTY) {
pr_dbg("%s: properties.num = %d\n", __func__, tvps->num);
goto out;
(tvp + i)->result = err;
}
- } else if (cmd == FE_GET_PROPERTY) {
+ } else if (cmd == V4L2_GET_PROPERTY) {
pr_dbg("%s: properties.num = %d\n", __func__, tvps->num);
pr_dbg("%s: properties.props = %p\n", __func__, tvps->props);
filp->f_flags);
break;
- case V4L2_SET_MODE: /* 0x566c */
+ case V4L2_SET_MODE: /* 0x4004566c */
ret = v4l2_frontend_set_mode(v4l2_fe, *((int *) arg));
break;
(enum v4l2_status *) arg);
break;
- case V4L2_SET_PROPERTY:
- case V4L2_GET_PROPERTY:
+ case V4L2_SET_PROPERTY: /* 0xc010566e */
+ case V4L2_GET_PROPERTY: /* 0xc010566f */
ret = v4l2_frontend_ioctl_properties(filp, cmd, arg);
break;
default:
+ pr_warn("%s: Unsupport cmd = 0x%x.\n", __func__, cmd);
break;
}
return -ENOMEM;
}
- v4l2_fe->search = v4l2_frontend_search;
fepriv = v4l2_fe->frontend_priv;
fepriv->v4l2dev = kzalloc(sizeof(struct v4l2_atvdemod_device),
#define V4L2_GET_EVENT _IOR('V', 107, struct v4l2_frontend_event)
#define V4L2_SET_MODE _IOW('V', 108, int)
#define V4L2_READ_STATUS _IOR('V', 109, enum v4l2_status)
-#define V4L2_SET_PROPERTY _IOW('V', 111, struct v4l2_properties)
-#define V4L2_GET_PROPERTY _IOR('V', 112, struct v4l2_properties)
+#define V4L2_SET_PROPERTY _IOWR('V', 110, struct v4l2_properties)
+#define V4L2_GET_PROPERTY _IOWR('V', 111, struct v4l2_properties)
-#define ANALOG_FLAG_ENABLE_AFC 0X00000001
+#define ANALOG_FLAG_ENABLE_AFC 0x00000001
#define ANALOG_FLAG_MANUL_SCAN 0x00000011
-#define V4L2_UNDEFINED 0
-#define V4L2_TUNE 1
-#define V4L2_NICAM 2
+#define V4L2_UNDEFINED 0
+#define V4L2_TUNE 1
+#define V4L2_SOUND_SYS 2
+#define V4L2_SLOW_SEARCH_MODE 3
+struct v4l2_frontend;
+
struct v4l2_analog_parameters {
unsigned int frequency;
unsigned int audmode;
/* DiSEqC, tone and parameters */
struct v4l2_property {
- __u32 cmd;
- __u32 reserved[3];
- union {
- __u32 data;
- struct {
- __u8 data[32];
- __u32 len;
- __u32 reserved1[3];
- void *reserved2;
- } buffer;
- } u;
+ unsigned int cmd;
+ unsigned int data;
int result;
-} __attribute__ ((__packed__));
+};
struct v4l2_properties {
- __u32 num;
- struct v4l2_property *props;
+ unsigned int num;
+ union {
+ struct v4l2_property *props;
+ __u64 reserved;
+ };
};
enum v4l2_search {
unsigned int tuner_id;
};
+struct v4l2_frontend_ops {
+ int (*set_property)(struct v4l2_frontend *fe,
+ struct v4l2_property *tvp);
+ int (*get_property)(struct v4l2_frontend *fe,
+ struct v4l2_property *tvp);
+
+ enum v4l2_search (*search)(struct v4l2_frontend *v4l2_fe);
+};
+
struct v4l2_frontend {
struct device *dev;
void *frontend_priv;
void *tuner_priv;
- void *analog_priv;
+ void *analog_demod_priv;
struct v4l2_analog_parameters params;
- enum v4l2_search (*search)(struct v4l2_frontend *v4l2_fe);
+ struct v4l2_frontend_ops ops;
};
struct v4l2_atvdemod_device {
struct i2c_client i2c;
unsigned int tuner_id;
-
- enum v4l2_search (*search)(struct v4l2_atvdemod_device *dev);
};
int v4l2_resister_frontend(struct v4l2_frontend *v4l2_fe);
#include <linux/types.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <linux/amlogic/iomap.h>
#include <linux/amlogic/cpu_version.h>
#include "atv_demod_debug.h"
#include "atvauddemod_func.h"
#include "aud_demod_settings.c"
+#include "atvdemod_func.h"
+#include "atv_demod_driver.h"
/* #define AUDIO_MOD_DET_INTERNAL */
unsigned int ademod_debug_en;
/* btsc_detect_delay for btsc detect delay */
unsigned int btsc_detect_delay = 10;
+unsigned int nicam_detect_delay = 10;
/* signal_audmode for btsc signal audio mode */
unsigned int signal_audmode;
unsigned int audio_thd_threshold1 = 0x1000;
unsigned int audio_thd_threshold2 = 0xf00;
+unsigned int audio_a2_auto = 1;
+unsigned int audio_a2_power_threshold = 0x1800;
+
#undef pr_info
#define pr_info(args...)\
do {\
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);
+ aa = (int)((54.6875e3+274.1)/(FCLK/16/4)*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);
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);
+ aa = (int)((54.6875e3+274.1)/(FCLK/16/4)*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);
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);
+ aa = (int)((54.6875e3+274.1)/(FCLK/16/4)*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);
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);
+ aa = (int)((54.6875e3+274.1)/(FCLK/16/4)*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);
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);
+ aa = (int)((54.6875e3+274.1)/(FCLK/16/4)*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);
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;
+ reg_value = adec_rd_reg(CARRIER_MAG_REPORT);
+ if (((reg_value >> 16) & 0xffff) < 0x400) {
+ *stereo_flag = 0;
+ *dual_flag = 0;
+ } else {
+ 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)
+ if (stereo_power > dual_power &&
+ stereo_power > audio_a2_power_threshold)
*stereo_flag = 1;
else
*stereo_flag = 0;
- if (stereo_power < dual_power && dual_power > 0x1800)
+ if (stereo_power < dual_power &&
+ dual_power > audio_a2_power_threshold)
*dual_flag = 1;
else
*dual_flag = 0;
}
+ /* 0:MONO 1:Stereo 2:Dual */
+ if (*dual_flag == 0 && *stereo_flag == 0)
+ signal_audmode = 0;
+ else if (*stereo_flag)
+ signal_audmode = 1;
+ else if (*dual_flag)
+ signal_audmode = 2;
}
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);
+ mdelay(btsc_detect_delay);
if (auto_en) {
reg_value = adec_rd_reg(AUDIO_MODE_REPORT);
*stereo_flag = reg_value&0x1;
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;
+ uint32_t reg_value = 0;
+ int nicam_lock = 0;
+ int cic = 0;
+
+ mdelay(nicam_detect_delay);
- reg_value = adec_rd_reg(0x1a3);
+ reg_value = adec_rd_reg(NICAM_LEVEL_REPORT);
nicam_lock = (reg_value>>28)&1;
- reg_value = adec_rd_reg(0x1a4);
+ reg_value = adec_rd_reg(NICAM_MODE_REPORT);
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;
+
+ /* 0:MONO 1:Stereo 2:Dual 3:NICAM MONO */
+ if (*nicam_mono_flag)
+ signal_audmode = 3;
+ else if (*nicam_stereo_flag)
+ signal_audmode = 1;
+ else if (*nicam_dual_flag)
+ signal_audmode = 2;
+ else
+ signal_audmode = 0;
}
void set_btsc_outputmode(uint32_t outmode)
{
- uint32_t reg_value;
- uint32_t tmp_value, tmp_value1;
- int stereo_flag, sap_flag;
+ uint32_t reg_value = 0;
+ uint32_t tmp_value = 0, tmp_value1 = 0;
+ int stereo_flag = 0, sap_flag = 0;
+ static int last_stereo_flag = -1, last_sap_flag = -1, last_mode = -1;
update_btsc_mode(1, &stereo_flag, &sap_flag);
+
+ /* ADEC_CTRL: 0x10
+ * bits[8]: Audio_mute, 1 = mute, 0 = not mute.
+ * bits[7:4]: Output select control.
+ * 0 = nicam mono / dual first.
+ * 1 = stereo / dual first + second.
+ * 2 = dual second.
+ * 3 = fm mono.
+ * bits[3:0]: Std_sel.
+ */
reg_value = adec_rd_reg(ADDR_ADEC_CTRL);
+ if (last_stereo_flag == stereo_flag
+ && last_sap_flag == sap_flag
+ && last_mode == outmode)
+ return;
+
+ /* priority: Stereo > MONO > SAP */
+ /* 0:MONO 1:Stereo 2:MONO+SAP 3:Stereo+SAP */
+ switch (signal_audmode) {
+ case 0: /* MONO */
+ if (outmode != AUDIO_OUTMODE_BTSC_MONO) {
+ outmode = AUDIO_OUTMODE_BTSC_MONO;
+ aud_mode = AUDIO_OUTMODE_BTSC_MONO;
+ }
+ break;
+ case 1: /* Stereo */
+ if (outmode != AUDIO_OUTMODE_BTSC_MONO &&
+ outmode != AUDIO_OUTMODE_BTSC_STEREO) {
+ outmode = AUDIO_OUTMODE_BTSC_STEREO;
+ aud_mode = AUDIO_OUTMODE_BTSC_STEREO;
+ }
+ break;
+ case 2: /* MONO+SAP */
+ if (outmode != AUDIO_OUTMODE_BTSC_MONO &&
+ outmode != AUDIO_OUTMODE_BTSC_SAP) {
+ outmode = AUDIO_OUTMODE_BTSC_MONO;
+ aud_mode = AUDIO_OUTMODE_BTSC_MONO;
+ }
+ break;
+ case 3: /* Stereo+SAP */
+ if (outmode != AUDIO_OUTMODE_BTSC_MONO &&
+ outmode != AUDIO_OUTMODE_BTSC_SAP &&
+ outmode != AUDIO_OUTMODE_BTSC_STEREO) {
+ outmode = AUDIO_OUTMODE_BTSC_STEREO;
+ aud_mode = AUDIO_OUTMODE_BTSC_STEREO;
+ }
+ break;
+ }
+
switch (outmode) {
case AUDIO_OUTMODE_BTSC_MONO:
tmp_value = (reg_value & 0xf) | (0 << 4);
}
break;
}
+
+ last_stereo_flag = stereo_flag;
+ last_sap_flag = sap_flag;
+ last_mode = outmode;
}
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);
+ int stereo_flag = 0, dual_flag = 0;
+ static int last_stereo_flag = -1, last_dual_flag = -1, last_mode = -1;
+
+ update_a2_eiaj_mode(audio_a2_auto, &stereo_flag, &dual_flag);
+
+ /* ADEC_CTRL: 0x10
+ * bits[8]: Audio_mute, 1 = mute, 0 = not mute.
+ * bits[7:4]: Output select control.
+ * 0 = nicam mono / dual first.
+ * 1 = stereo / dual first + second.
+ * 2 = dual second.
+ * 3 = fm mono.
+ * bits[3:0]: Std_sel.
+ */
reg_value = adec_rd_reg(ADDR_ADEC_CTRL);
+ if (last_stereo_flag == stereo_flag
+ && last_dual_flag == dual_flag
+ && last_mode == outmode)
+ return;
+
+ set_output_left_right_exchange(1);
+
+ /* priority: Stereo > NICAM MONO > Dual > FM MONO */
+ /* 0:MONO 1:Stereo 2:Dual */
+ switch (signal_audmode) {
+ case 0: /* MONO */
+ if (outmode != AUDIO_OUTMODE_A2_MONO) {
+ outmode = AUDIO_OUTMODE_A2_MONO;
+ aud_mode = AUDIO_OUTMODE_A2_MONO;
+ }
+ break;
+ case 1: /* Stereo */
+ if (outmode != AUDIO_OUTMODE_A2_MONO &&
+ outmode != AUDIO_OUTMODE_A2_STEREO) {
+ outmode = AUDIO_OUTMODE_A2_STEREO;
+ aud_mode = AUDIO_OUTMODE_A2_STEREO;
+ }
+ break;
+ case 2: /* Dual */
+ if (outmode != AUDIO_OUTMODE_A2_MONO &&
+ outmode != AUDIO_OUTMODE_A2_DUAL_A &&
+ outmode != AUDIO_OUTMODE_A2_DUAL_B &&
+ outmode != AUDIO_OUTMODE_A2_DUAL_AB) {
+ outmode = AUDIO_OUTMODE_A2_DUAL_A;
+ aud_mode = AUDIO_OUTMODE_A2_DUAL_A;
+ }
+ break;
+ }
+
switch (outmode) {
case AUDIO_OUTMODE_A2_MONO:
tmp_value = (reg_value&0xf)|(0<<4);
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);
- }
+ tmp_value = (reg_value&0xf)|(1<<4);
+ adec_wr_reg(ADDR_ADEC_CTRL, tmp_value);
+ set_output_left_right_exchange(0);
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);
- }
+ 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);
- }
+ tmp_value = (reg_value&0xf)|(2<<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);
- }
+ tmp_value = (reg_value&0xf)|(3<<4);
+ adec_wr_reg(ADDR_ADEC_CTRL, tmp_value);
+ set_output_left_right_exchange(0);
break;
}
+
+ last_stereo_flag = stereo_flag;
+ last_dual_flag = dual_flag;
+ last_mode = outmode;
}
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;
+ int nicam_mono_flag = 0, nicam_stereo_flag = 0, nicam_dual_flag = 0;
+ int nicam_lock = 0;
+ static int last_nicam_lock = -1, last_mono_flag = -1;
+ static int last_stereo_flag = -1, last_dual_flag = -1, last_mode = -1;
update_nicam_mode(&nicam_lock, &nicam_mono_flag,
&nicam_stereo_flag, &nicam_dual_flag);
+ /* ADEC_CTRL: 0x10
+ * bits[8]: Audio_mute, 1 = mute, 0 = not mute.
+ * bits[7:4]: Output select control.
+ * 0 = nicam mono / dual first.
+ * 1 = stereo / dual first + second.
+ * 2 = dual second.
+ * 3 = fm mono.
+ * bits[3:0]: Std_sel.
+ */
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);
+
+ if (last_nicam_lock == nicam_lock
+ && last_mono_flag == nicam_mono_flag
+ && last_stereo_flag == nicam_stereo_flag
+ && last_dual_flag == nicam_dual_flag
+ && last_mode == outmode)
+ return;
+
+ set_output_left_right_exchange(1);
+
+ /* priority: Stereo > NICAM MONO > Dual > FM MONO */
+ /* 0:FM MONO 1:Stereo 2:Dual 3:NICAM MONO */
+ switch (signal_audmode) {
+ case 0: /* FM MONO */
+ if (outmode != AUDIO_OUTMODE_NICAM_MONO) {
+ outmode = AUDIO_OUTMODE_NICAM_MONO;
+ aud_mode = AUDIO_OUTMODE_NICAM_MONO;
}
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);
+ case 1: /* Stereo */
+ if (outmode != AUDIO_OUTMODE_NICAM_MONO &&
+ outmode != AUDIO_OUTMODE_NICAM_STEREO) {
+ outmode = AUDIO_OUTMODE_NICAM_STEREO;
+ aud_mode = AUDIO_OUTMODE_NICAM_STEREO;
+ }
+ break;
+ case 2: /* Dual */
+ if (outmode != AUDIO_OUTMODE_NICAM_MONO &&
+ outmode != AUDIO_OUTMODE_NICAM_DUAL_A &&
+ outmode != AUDIO_OUTMODE_NICAM_DUAL_B &&
+ outmode != AUDIO_OUTMODE_NICAM_DUAL_AB) {
+ outmode = AUDIO_OUTMODE_NICAM_DUAL_A;
+ aud_mode = AUDIO_OUTMODE_NICAM_DUAL_A;
+ }
+ break;
+ case 3: /* NICAM MONO */
+ if (outmode != AUDIO_OUTMODE_NICAM_MONO &&
+ outmode != AUDIO_OUTMODE_NICAM_MONO1) {
+ outmode = AUDIO_OUTMODE_NICAM_MONO1;
+ aud_mode = AUDIO_OUTMODE_NICAM_MONO1;
}
break;
+ }
+
+ switch (outmode) {
+ case AUDIO_OUTMODE_NICAM_MONO:/* fm mono */
+ if (aud_std == AUDIO_STANDARD_NICAM_BG)
+ tmp_value = (AUDIO_STANDARD_A2_BG & 0xf) | (0 << 4);
+ else if (aud_std == AUDIO_STANDARD_NICAM_DK)
+ tmp_value = (AUDIO_STANDARD_A2_DK2 & 0xf) | (0 << 4);
+ else if (aud_std == AUDIO_STANDARD_NICAM_I)
+ tmp_value = (AUDIO_STANDARD_CHINA & 0xf) | (0 << 4);
+ else if (aud_std == AUDIO_STANDARD_NICAM_L)
+ tmp_value = (AUDIO_STANDARD_MONO_ONLY & 0xf) | (0 << 4);
+ adec_wr_reg(ADDR_ADEC_CTRL, tmp_value);
+ break;
+
+ case AUDIO_OUTMODE_NICAM_MONO1:/* nicam mono */
+ if ((reg_value & 0xf) != (aud_std & 0xf))
+ reg_value = (reg_value & ~0xf) | (aud_std & 0xf);
+
+ tmp_value = (reg_value&0xf)|(0<<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);
- }
+ if ((reg_value & 0xf) != (aud_std & 0xf))
+ reg_value = (reg_value & ~0xf) | (aud_std & 0xf);
+
+ tmp_value = (reg_value&0xf)|(1<<4);
+ adec_wr_reg(ADDR_ADEC_CTRL, tmp_value);
+ set_output_left_right_exchange(0);
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);
- }
+ if ((reg_value & 0xf) != (aud_std & 0xf))
+ reg_value = (reg_value & ~0xf) | (aud_std & 0xf);
+
+ tmp_value = (reg_value&0xf)|(0<<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);
- }
+ if ((reg_value & 0xf) != (aud_std & 0xf))
+ reg_value = (reg_value & ~0xf) | (aud_std & 0xf);
+
+ tmp_value = (reg_value&0xf)|(2<<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);
- }
+ if ((reg_value & 0xf) != (aud_std & 0xf))
+ reg_value = (reg_value & ~0xf) | (aud_std & 0xf);
+
+ tmp_value = (reg_value&0xf)|(1<<4);
+ adec_wr_reg(ADDR_ADEC_CTRL, tmp_value);
+ set_output_left_right_exchange(0);
break;
}
- pr_info("%s tmp_value :0x%x\n", __func__, reg_value);
+
+ pr_info("[%s] tmp_value: 0x%x.\n", __func__, reg_value);
+
+ last_nicam_lock = nicam_lock;
+ last_mono_flag = nicam_mono_flag;
+ last_stereo_flag = nicam_stereo_flag;
+ last_dual_flag = nicam_dual_flag;
+ last_mode = outmode;
}
void set_outputmode(uint32_t standard, uint32_t outmode)
}
}
+void set_output_left_right_exchange(unsigned int ch)
+{
+ unsigned int read = 0;
+
+ if (amlatvdemod_devp->audio_demod_reg_base == NULL)
+ return;
+
+ read = readl(amlatvdemod_devp->audio_demod_reg_base);
+
+ if ((read & (1 << 2)) != ((ch & 0x01) << 2))
+ writel((read & ~(1 << 2)) | ((ch & 0x01) << 2),
+ amlatvdemod_devp->audio_demod_reg_base);
+}
+
#endif /* __ATVAUDDEMOD_FUN_H */
#include "aud_demod_reg.h"
+extern unsigned int signal_audmode;
extern int atvaudiodem_reg_read(unsigned int reg, unsigned int *val);
extern int atvaudiodem_reg_write(unsigned int reg, unsigned int val);
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);
+void set_output_left_right_exchange(unsigned int ch);
+
#endif /* __ATVAUDDEMOD_H_ */
unsigned int audio_gain_val = 512;
unsigned int audio_a2_threshold = 0x800;
unsigned int audio_a2_delay = 10;
-
+unsigned int audio_nicam_delay = 100;
enum AUDIO_SCAN_ID {
ID_PAL_I = 0,
data = atv_dmd_rd_byte(APB_BLOCK_ADDR_VDAGC, 0x4f);
line_lock = data & 0x10;
line_lock_strong = data & 0x8;
-
- pr_dbg("line_lock = 0x%x, line_lock_strong = 0x%x\n",
- line_lock, line_lock_strong);
-
+ /*
+ * pr_dbg("line_lock = 0x%x, line_lock_strong = 0x%x\n",
+ * line_lock, line_lock_strong);
+ */
*lock = (line_lock | line_lock_strong);
}
*power = data & 0xffff;
}
- pr_dbg("retrieve_vpll_carrier_audio_power: %d.\n", *power);
+ pr_audio("retrieve_vpll_carrier_audio_power: %d.\n", *power);
}
int retrieve_vpll_carrier_afc(void)
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);
+*/
+ set_outputmode(aud_std, aud_mode);
if (non_std_onoff)
atv_dmd_non_std_set(true);
switch (broad_std) {
case AML_ATV_DEMOD_VIDEO_MODE_PROP_NTSC:
- std = AUDIO_STANDARD_BTSC;
+ std = AUDIO_STANDARD_A2_K;
configure_adec(std);
adec_soft_reset();
msleep(audio_a2_delay);
std = AUDIO_STANDARD_NICAM_BG;
configure_adec(std);
adec_soft_reset();
- mdelay(2);
+ mdelay(audio_nicam_delay);
/* need wait */
- reg_value = adec_rd_reg(0x1a3);
+ reg_value = adec_rd_reg(NICAM_LEVEL_REPORT);
nicam_lock = (reg_value>>28)&1;
-
+ pr_info("\n%s 0x%x\n", __func__, reg_value);
if (nicam_lock)
std = AUDIO_STANDARD_NICAM_BG;
else
break;
case AML_ATV_DEMOD_VIDEO_MODE_PROP_PAL_DK:
std = AUDIO_STANDARD_NICAM_DK;
- configure_adec(aud_std);
+ configure_adec(std);
adec_soft_reset();
- mdelay(2);
+ mdelay(audio_nicam_delay);
/* need wait */
- reg_value = adec_rd_reg(0x1a3);
+ reg_value = adec_rd_reg(NICAM_LEVEL_REPORT);
nicam_lock = (reg_value>>28)&1;
+ pr_info("\n%s 0x%x\n", __func__, reg_value);
if (nicam_lock)
std = AUDIO_STANDARD_NICAM_DK;
else
if_inv = amlatvdemod_devp->if_inv;
}
- pr_info
- ("[atvdemod..]%s: broad_std %d,hz_cvrt:0x%x, offset:%d,std:0x%x.\n",
- __func__, broad_std, freq_hz_cvrt, amlatvdemod_devp->fre_offset,
- (unsigned int) ptstd);
+ pr_info("[%s] set broad_std %d, hz_cvrt 0x%x, offset %d.\n",
+ __func__, broad_std, freq_hz_cvrt,
+ amlatvdemod_devp->fre_offset);
+
+ pr_info("[%s] set std color %s, audio type %s.\n",
+ __func__,
+ v4l2_std_to_str((0xff000000 & amlatvdemod_devp->std)),
+ v4l2_std_to_str((0xffffff & amlatvdemod_devp->std)));
+
+ pr_info("[%s] set if_freq %d, if_inv %d.\n",
+ __func__, amlatvdemod_devp->if_freq,
+ amlatvdemod_devp->if_inv);
if (atvdemod_init())
pr_info("[%s]: atv restart error.\n", __func__);
extern unsigned int reg_23cf; /* IIR filter */
extern int broad_std_except_pal_m;
+extern unsigned int aud_std;
+extern unsigned int aud_mode;
#define ATVDEMOD_INTERVAL (HZ/100) /*10ms, #define HZ 100*/
#define CARRIER_MAG_REPORT 0x0f6
#define BTSC_AB_REPORT 0x0f7
#define AUDIO_MODE_REPORT 0x0f8
+#define NICAM_LEVEL_REPORT 0x1a3
+#define NICAM_MODE_REPORT 0x1a4
#define CTRL_SEL 0x0ff
#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_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_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_INDIAN 0x0F
+#define AUDIO_STANDARD_BTSC_SA 0x10
#define AUDIO_STANDARD_MONO_ONLY 0x11
#define AUDIO_OUTMODE_MONO 0
__func__, adc_pll_chg);
break;
}
+ if (adc_pll_chg & ADC_EN_ATV_DEMOD) {
+ tvafe_pr_info("%s:ADEMOD ATV had done!:%d\n",
+ __func__, adc_pll_chg);
+ break;
+ }
mutex_lock(&pll_mutex);
do {
if (tvafe_cpu_type() == CPU_TYPE_TXL ||