You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 lines
6.0 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright (c) Hisilicon Technologies Co., Ltd. 2017-2021. All rights reserved.
* Description: A8300 LNB driver
* Author: Hisilicon
* Create: 2017/10/23
*/
#include "drv_lnbctrl.h"
#include "drv_i2c_ext.h"
#define A8300_ADDR 0x10
#define A8300_CTRL_REG0_ADDR 0
#define A8300_CTRL_REG1_ADDR 1
#define A8300_STATUS_REG0_ADDR 0
#define A8300_I2C_WRITE_TIMES 1
static td_bool g_a8300_inited = TD_FALSE;
static td_u8 g_reg1_data = 0;
static td_u8 g_reg2_data = 0;
static td_u32 g_a8300_port = 0;
static td_s32 a8300_read_byte(lnbctrl_dev_param* param, td_u8 reg_addr, td_u8 *reg_val)
{
td_s32 ret;
if (reg_val == TD_NULL) {
soc_log_err("pointer is null\n");
return SOC_ERR_FRONTEND_INVALID_POINT;
}
ret = ext_drv_i2c_read_2stop(param->i2c_num, param->dev_addr, reg_addr, 1, reg_val, 1);
if (ret != TD_SUCCESS) {
soc_log_err("A8300 read i2c 0x%02x failed.\n", *reg_val);
return ret;
}
return TD_SUCCESS;
}
td_s32 a8300_write_byte(lnbctrl_dev_param* param, td_u8 reg_addr, td_u8 reg_val)
{
td_s32 ret;
ret = ext_drv_i2c_write(param->i2c_num, param->dev_addr, reg_addr, 1, &reg_val, 1);
if (ret != TD_SUCCESS) {
soc_log_err("A8300 write i2c failed, %x\n", ret);
return ret;
}
soc_log_info("A8300 write i2c 0x%02x ok.\n", reg_val);
return TD_SUCCESS;
}
td_s32 a8300_init(td_u32 port, td_u8 i2c_channel, td_u8 dev_addr)
{
td_s32 ret;
td_u8 reg_val = 0x80;
lnbctrl_dev_param* param = TD_NULL;
if (g_a8300_inited) {
return TD_SUCCESS;
}
g_reg1_data = 0;
g_reg2_data = 0;
/* 添加一个node,所有port共用一个 pstParam */
g_a8300_port = port;
param = lnbctrl_queue_get(g_a8300_port);
if (param == TD_NULL) {
param = lnbctrl_queue_insert(g_a8300_port, i2c_channel, dev_addr);
if (param == TD_NULL) {
soc_log_err("lnbctrl_queue_insert failed.\n");
return TD_FAILURE;
}
}
if (!param->inited) {
/* 初始化,寄存器写0。如果不先读一下寄存器的话首次写入会失效原因待查。 */
ret = a8300_read_byte(param, A8300_STATUS_REG0_ADDR, &reg_val);
if (ret != TD_SUCCESS) {
soc_log_err("a8300_read_byte 0x%x failed.\n", reg_val);
return ret;
}
ret = a8300_write_byte(param, A8300_STATUS_REG0_ADDR, 0);
if (ret != TD_SUCCESS) {
soc_log_err("a8300_write_byte failed.\n");
return ret;
}
reg_val = g_reg1_data;
reg_val |= 0x20; /* 22k波形由外部产生 */
ret = a8300_write_byte(param, A8300_CTRL_REG0_ADDR, reg_val);
if (ret != TD_SUCCESS) {
soc_log_err("a8300_write_byte 0x%x failed.\n", reg_val);
return ret;
}
g_reg1_data = reg_val;
param->inited = TD_TRUE;
}
g_a8300_inited = TD_TRUE;
return TD_SUCCESS;
}
td_s32 a8300_standby(td_u32 tuner_port, td_u32 standby)
{
return TD_SUCCESS;
}
td_s32 a8300_lnbctrl_power(td_u32 tuner_port, td_u8 power)
{
td_s32 ret;
td_u8 reg_val;
lnbctrl_dev_param* param;
/* Find node */
param = lnbctrl_queue_get(g_a8300_port);
if (param == TD_NULL) {
soc_log_err("lnbctrl_queue_get failed.\n");
return TD_FAILURE;
}
reg_val = g_reg1_data;
if (power == 0) {
reg_val &= 0xe0;
} else {
reg_val |= 0x10;
}
ret = a8300_write_byte(param, A8300_CTRL_REG0_ADDR, reg_val);
if (ret != TD_SUCCESS) {
soc_log_err("a8300_write_byte failed.\n");
return ret;
}
g_reg1_data = reg_val;
return TD_SUCCESS;
}
td_s32 a8300_set_lnb_out(td_u32 tuner_port, frontend_lnb_out_level out)
{
td_s32 ret;
lnbctrl_dev_param* param;
td_u8 reg;
param = lnbctrl_queue_get(g_a8300_port);
if (param == TD_NULL) {
soc_log_err("lnbctrl_queue_get failed.\n");
return TD_FAILURE;
}
if (!param->inited) {
soc_log_err("pstParam uninited.\n");
return TD_FAILURE;
}
reg = g_reg1_data;
switch (out) {
case FRONTEND_LNB_OUT_0V:
case FRONTEND_LNB_OUT_BUTT:
reg &= 0xe0;
break;
case FRONTEND_LNB_OUT_13V:
reg &= 0xe0;
reg |= 0x12;
break;
case FRONTEND_LNB_OUT_14V:
reg &= 0xe0;
reg |= 0x13;
break;
case FRONTEND_LNB_OUT_18V:
reg &= 0xe0;
reg |= 0x1b;
break;
case FRONTEND_LNB_OUT_19V:
reg &= 0xe0;
reg |= 0x1c;
break;
default:
soc_log_err("Unkown enout: %d.\n", out);
return TD_FAILURE;
}
ret = a8300_write_byte(param, A8300_CTRL_REG0_ADDR, reg);
if (ret != TD_SUCCESS) {
soc_log_err("a8300_write_byte 0x%x failed.\n", reg);
return ret;
}
g_reg1_data = reg;
return TD_SUCCESS;
}
td_s32 a8300_deinit(td_u32 tuner_port)
{
lnbctrl_dev_param* param;
td_s32 ret;
/* Find node */
param = lnbctrl_queue_get(g_a8300_port);
if (param == TD_NULL) {
soc_log_info("lnbctrl_queue_get failed.\n");
return TD_SUCCESS;
}
/* A8300 power off */
ret = a8300_lnbctrl_power(g_a8300_port, 0);
if (ret != TD_SUCCESS) {
soc_log_err("a8300_lnbctrl_power0 failed.\n");
return TD_FAILURE;
}
lnbctrl_queue_remove(g_a8300_port);
g_a8300_inited = TD_FALSE;
g_reg1_data = 0;
g_reg2_data = 0;
g_a8300_port = 0;
return TD_SUCCESS;
}
td_s32 drv_fe_adp_a8300_regist_func(drv_fe_lnb_ops *lnb_ops)
{
drv_fe_check_pointer(lnb_ops);
lnb_ops->init = a8300_init;
lnb_ops->deinit = a8300_deinit;
lnb_ops->standby = a8300_standby;
lnb_ops->set_lnb_out = a8300_set_lnb_out;
return TD_SUCCESS;
}