blob: 8de310280953da732d937852aeac6ebc2958f884 [file] [log] [blame]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#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);
}