AMLOGIC ATV DEMOD DRIVER
M: nengwen.chen <nengwen.chen@amlogic.com>
-F: include/linux/amlogic/aml_atvdemod.h
F: drivers/amlogic/atv_demod/*
+F: include/linux/amlogic/aml_atvdemod.h
AMLOGIC ADD EXT MIPI DEFAULT DRIVER
M: Weiming Liu <weiming.liu@amlogic.com>
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0xff656000 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0xff656000 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0xff656000 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0xff656000 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0xff656000 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0xff656000 0x2000 /* demod reg */
/dts-v1/;
#include "mesontm2.dtsi"
-#include "partition_mbox_normal.dtsi"
+#include "partition_mbox_normal_P_32.dtsi"
/ {
model = "Amlogic TM2 T962E2 AB311";
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */
status = "okay";
tuner = <&tuner>;
btsc_sap_mode = <1>;
+ interrupts = <0 236 1>;
/* pinctrl-names="atvdemod_agc_pins"; */
/* pinctrl-0=<&atvdemod_agc_pins>; */
reg = <0x0 0xff656000 0x0 0x2000 /* demod reg */
atv_demod_afc.o \
atv_demod_monitor.o \
atv_demod_access.o \
- atv_demod_debug.o
+ atv_demod_debug.o \
+ atv_demod_isr.o \
ccflags-y += -I.
ccflags-y += -Idrivers/media/dvb-core
\ No newline at end of file
DEBUGFS_CREATE_NODE(audio_gain_lpr, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(audio_atv_ov, 0640, dentry, u32)\
DEBUGFS_CREATE_NODE(audio_atv_ov_flag, 0640, dentry, u32)\
+ DEBUGFS_CREATE_NODE(atvdemod_isr_en, 0640, dentry, bool)\
}
#define pr_info(fmt, ...)\
do {\
if (1)\
- printk(fmt, ##__VA_ARGS__);\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
} while (0)
#undef pr_dbg
#define pr_dbg(fmt, ...)\
do {\
if (atvdemod_debug_en & 0x01)\
- printk(fmt, ##__VA_ARGS__);\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
} while (0)
#undef pr_err
#define pr_err(fmt, ...)\
do {\
if (1)\
- printk(fmt, ##__VA_ARGS__);\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
} while (0)
#undef pr_afc
#define pr_afc(fmt, ...)\
do {\
if (atvdemod_debug_en & 0x02)\
- printk(fmt, ##__VA_ARGS__);\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
} while (0)
#undef pr_warn
#define pr_warn(fmt, ...)\
do {\
if (1)\
- printk(fmt, ##__VA_ARGS__);\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
} while (0)
#undef pr_audio
#define pr_audio(fmt, ...)\
do {\
if (atvdemod_debug_en & 0x04)\
- printk(fmt, ##__VA_ARGS__);\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
} while (0)
+#undef pr_isr
+#define pr_isr(fmt, ...)\
+ do {\
+ if (atvdemod_debug_en & 0x08)\
+ printk("atv_demod: "fmt, ##__VA_ARGS__);\
+ } while (0)
#if defined(CONFIG_DEBUG_FS)
#define AML_ATVDEMOD_DEBUGFS
if (!dev)
return -ENOMEM;
+ amlatvdemod_devp = dev;
+
dev->name = ATVDEMOD_DEVICE_NAME;
dev->dev = &pdev->dev;
dev->cls.name = ATVDEMOD_DEVICE_NAME;
goto fail_class_register;
}
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!res) {
+ dev->irq = -1;
+ pr_err("can't get irq resource.\n");
+ } else {
+ dev->irq = res->start;
+ pr_err("get irq resource %d.\n", dev->irq);
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
pr_err("no demod memory resource.\n");
platform_set_drvdata(pdev, dev);
- amlatvdemod_devp = dev;
-
pr_info("%s: OK.\n", __func__);
return 0;
fail_class_register:
kfree(dev->tuners);
kfree(dev);
+ amlatvdemod_devp = NULL;
pr_info("%s: fail.\n", __func__);
bool analog_attached;
bool tuner_attached;
+ int irq;
+
void __iomem *demod_reg_base;
void __iomem *audiodemod_reg_base;
void __iomem *hiu_reg_base;
--- /dev/null
+/*
+ * drivers/amlogic/atv_demod/atv_demod_isr.c
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include "atv_demod_isr.h"
+#include "atvdemod_func.h"
+#include "atv_demod_access.h"
+#include "atv_demod_debug.h"
+
+static DEFINE_MUTEX(isr_mutex);
+
+bool atvdemod_isr_en;
+
+static void atv_demod_reset_irq(void)
+{
+ atv_dmd_wr_long(APB_BLOCK_ADDR_INTERPT_MGT, 0x10, 0x3);
+ atv_dmd_wr_long(APB_BLOCK_ADDR_INTERPT_MGT, 0x10, 0x0);
+}
+
+static void atv_demod_set_irq(bool enable)
+{
+ if (enable)
+ atv_dmd_wr_long(APB_BLOCK_ADDR_INTERPT_MGT, 0x14, 0x0);
+ else
+ atv_dmd_wr_long(APB_BLOCK_ADDR_INTERPT_MGT, 0x14, 0xf);
+}
+
+static int atv_demod_get_irq_status(void)
+{
+ return atv_dmd_rd_long(APB_BLOCK_ADDR_INTERPT_MGT, 0x18);
+}
+
+static irqreturn_t atv_demod_isr_handler(int irq, void *dev)
+{
+ int status = atv_demod_get_irq_status();
+
+ pr_isr("irq status: 0x%x.\n", status);
+ pr_isr("line_unlock: %s.\n",
+ (status & 0x80) ? "unlocked" : "locked");
+ pr_isr("line_strong_unlock: %s.\n",
+ (status & 0x40) ? "unlocked" : "locked");
+ pr_isr("field_unlock: %s.\n",
+ (status & 0x20) ? "unlocked" : "locked");
+ pr_isr("pll_unlock: %s.\n",
+ (status & 0x10) ? "unlocked" : "locked");
+
+ pr_isr("line_lock: %s.\n",
+ (status & 0x08) ? "locked" : "unlocked");
+ pr_isr("line_strong_lock: %s.\n",
+ (status & 0x04) ? "locked" : "unlocked");
+ pr_isr("field_lock: %s.\n",
+ (status & 0x02) ? "locked" : "unlocked");
+ pr_isr("pll_lock: %s.\n\n",
+ (status & 0x01) ? "locked" : "unlocked");
+
+ atv_demod_reset_irq();
+
+ return IRQ_HANDLED;
+}
+
+static void atv_demod_isr_disable(struct atv_demod_isr *isr)
+{
+ mutex_lock(&isr->mtx);
+
+ if (atvdemod_isr_en && isr->init && isr->state == true) {
+ atv_demod_set_irq(false);
+ disable_irq(isr->irq);
+ isr->state = false;
+ }
+
+ mutex_unlock(&isr->mtx);
+
+ pr_isr("%s: state: %d.\n", __func__, isr->state);
+}
+
+static void atv_demod_isr_enable(struct atv_demod_isr *isr)
+{
+ mutex_lock(&isr->mtx);
+
+ if (atvdemod_isr_en && isr->init && isr->state == false) {
+ atv_demod_reset_irq();
+ atv_demod_set_irq(true);
+ enable_irq(isr->irq);
+ isr->state = true;
+ }
+
+ mutex_unlock(&isr->mtx);
+
+ pr_isr("%s: state: %d.\n", __func__, isr->state);
+}
+
+void atv_demod_isr_init(struct atv_demod_isr *isr)
+{
+ int ret = 0;
+
+ mutex_lock(&isr_mutex);
+
+ mutex_init(&isr->mtx);
+
+ isr->state = false;
+ isr->disable = atv_demod_isr_disable;
+ isr->enable = atv_demod_isr_enable;
+ isr->handler = atv_demod_isr_handler;
+
+ ret = request_irq(isr->irq, isr->handler, IRQF_SHARED,
+ "atv_demod_irq", (void *) isr);
+ if (ret != 0) {
+ isr->init = false;
+ pr_err("atv_demod_isr request irq error: %d.\n", ret);
+ } else {
+ isr->init = true;
+ disable_irq_nosync(isr->irq);
+ }
+
+ mutex_unlock(&isr_mutex);
+}
+
+void atv_demod_isr_uninit(struct atv_demod_isr *isr)
+{
+ mutex_lock(&isr_mutex);
+
+ if (isr->init) {
+ free_irq(isr->irq, (void *) isr);
+ isr->init = false;
+ isr->state = false;
+ }
+
+ mutex_unlock(&isr_mutex);
+}
--- /dev/null
+/*
+ * drivers/amlogic/atv_demod/atv_demod_isr.h
+ *
+ * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef __ATV_DEMOD_ISR_H__
+#define __ATV_DEMOD_ISR_H__
+
+#include <linux/mutex.h>
+#include <linux/interrupt.h>
+
+
+struct atv_demod_isr {
+ struct mutex mtx;
+
+ unsigned int irq;
+
+ bool init;
+ bool state;
+
+ void (*disable)(struct atv_demod_isr *isr);
+ void (*enable)(struct atv_demod_isr *isr);
+
+ irqreturn_t (*handler)(int irq, void *dev);
+};
+
+extern void atv_demod_isr_init(struct atv_demod_isr *isr);
+extern void atv_demod_isr_uninit(struct atv_demod_isr *isr);
+
+#endif /* __ATV_DEMOD_ISR_H__ */
#include "atv_demod_v4l2.h"
#include "atv_demod_afc.h"
#include "atv_demod_monitor.h"
+#include "atv_demod_isr.h"
#define DEVICE_NAME "aml_atvdemod"
int atv_demod_enter_mode(struct dvb_frontend *fe)
{
int err_code = 0;
+ struct atv_demod_priv *priv = fe->analog_demod_priv;
if (amlatvdemod_devp->pin_name != NULL) {
amlatvdemod_devp->agc_pin =
return -1;
}
- /* aml_afc_timer_enable(fe); */
- /* aml_demod_timer_enable(fe); */
+ if (priv->isr.enable)
+ priv->isr.enable(&priv->isr);
amlatvdemod_devp->std = 0;
amlatvdemod_devp->audmode = 0;
usleep_range(30 * 1000, 30 * 1000 + 100);
+ if (priv->isr.disable)
+ priv->isr.disable(&priv->isr);
+
if (priv->afc.disable)
priv->afc.disable(&priv->afc);
atv_demod_leave_mode(fe);
- if (priv)
+ if (priv) {
+ if (amlatvdemod_devp->irq > 0)
+ atv_demod_isr_uninit(&priv->isr);
instance = hybrid_tuner_release_state(priv);
+ }
if (instance == 0)
fe->analog_demod_priv = NULL;
priv->monitor.fe = fe;
atv_demod_monitor_init(&priv->monitor);
+ if (amlatvdemod_devp->irq > 0) {
+ priv->isr.irq = amlatvdemod_devp->irq;
+ atv_demod_isr_init(&priv->isr);
+ }
+
priv->standby = true;
pr_info("%s: aml_atvdemod found.\n", __func__);
#include "atv_demod_driver.h"
#include "atv_demod_afc.h"
#include "atv_demod_monitor.h"
+#include "atv_demod_isr.h"
#define AML_ATVDEMOD_UNINIT 0x0
struct atv_demod_monitor monitor;
+ struct atv_demod_isr isr;
+
int state;
bool scanning;
};
void aud_demod_clk_gate(int on)
{
if (on)
- adec_wr_reg(1, 0xf13);
+ adec_wr_reg(TOP_GATE_CLK, 0xf13);
else
- adec_wr_reg(1, 0);
+ adec_wr_reg(TOP_GATE_CLK, 0);
}
void configure_adec(int Audio_mode)
* set gate clk for btsc and nicam .
*/
if (is_meson_txhd_cpu() || is_meson_tl1_cpu() || is_meson_tm2_cpu())
- adec_wr_reg(0x28, 0xa);
+ adec_wr_reg(BTSC_NICAM_GATE_CLK, 0xa);
set_standard(Audio_mode);
#ifndef __AUD_DEMOD_REG_H__
#define __AUD_DEMOD_REG_H__
+#define TOP_GATE_CLK 0x001
#define ADEC_CTRL 0x010
#define FREQ0_CTRL 0x011
#define FREQ1_CTRL 0x012
#define SAP_DET_THD 0x025
#define MODE_DET_CNT_THD 0x026
#define ADEC_RESET 0x027
+#define BTSC_NICAM_GATE_CLK 0x028
+#define LR_GAIN_ADJ 0x029
#define DDC_FIR_COEF0_0 0x030
#define DDC_FIR_COEF0_1 0x031