/* * 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, ®_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, ®_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; }