sdk-hwV1.3/lichee/rtos-hal/hal/source/vin/utility/vin_supply.c

307 lines
6.9 KiB
C

/*
* vin_supply.c
*
* Copyright (c) 2018 by Allwinnertech Co., Ltd. http://www.allwinnertech.com
*
* Authors: Zequn Zheng <zequnzhengi@allwinnertech.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <sunxi_hal_twi.h>
#include "vin_supply.h"
#include "../platform/platform_cfg.h"
#include "../vin_video/vin_core.h"
extern struct vin_core *global_vinc[VIN_MAX_VIDEO];
int sunxi_vin_get_csi_top_irq(void)
{
return SUNXI_IRQ_CSI_TOP_PKT;
}
int sunxi_vin_get_isp_irq(int id)
{
return vin_isp_irq[id];
}
unsigned long sunxi_vin_get_top_base(void)
{
return (unsigned long)CSI_TOP_REGS_BASE;
}
unsigned long sunxi_vin_get_ccu_base(void)
{
return (unsigned long)CSI_CCU_REGS_BASE;
}
unsigned long sunxi_vin_get_mipi_base(void)
{
return (unsigned long)vin_mipi_base[0];
}
unsigned long sunxi_vin_get_mipiphy_base(int id)
{
return (unsigned long)vin_mipi_base[1 + id];
}
unsigned long sunxi_vin_get_mipiport_base(int id)
{
return (unsigned long)vin_mipi_base[3 + id];
}
unsigned long sunxi_vin_get_csi_base(int id)
{
return (unsigned long)vin_csi_base[id];
}
unsigned long sunxi_vin_get_isp_base(int id)
{
return (unsigned long)vin_isp_base[id/DEV_VIRT_NUM];
}
unsigned long sunxi_vin_get_scaler_base(int id)
{
return (unsigned long)vin_scaler_base[id/DEV_VIRT_NUM];
}
int sunxi_vin_get_vipp_irq(int id)
{
return vin_vipp_irq[id/DEV_VIRT_NUM];
}
int vin_vinc_parser(unsigned int id)
{
struct vin_core *vinc = global_vinc[id];
vinc->used = global_video[id].used;
vinc->csi_sel = global_video[id].csi_sel;
vinc->mipi_sel = global_video[id].mipi_sel;
vinc->isp_sel = global_video[id].isp_sel;
vinc->tdm_rx_sel = global_video[id].tdm_rx_sel;
vinc->isp_tx_ch = global_video[id].isp_tx_ch;
vinc->rear_sensor = global_video[id].rear_sensor;
return 0;
}
int sunxi_twi_init(int id)
{
int slave_addr;
twi_port_t port;
slave_addr = global_sensors[id].sensor_twi_addr >> 1;
port = global_sensors[id].sensor_twi_id;
hal_twi_init(port);
hal_twi_control(port, I2C_SLAVE, &slave_addr);
hal_writel(0x135, 0x02000340);
vin_log(VIN_LOG_POWER, "%s:id=%d, slave=0x%x\n", __func__, port, slave_addr);
return 0;
}
int sunxi_twi_exit(int id)
{
twi_port_t port;
port = global_sensors[id].sensor_twi_id;
hal_twi_uninit(port);
return 0;
}
int vin_set_pmu_channel(int on)
{
return 0;
}
int vin_gpio_set_status(int id, enum gpio_type gpio_id, unsigned int status)
{
gpio_pin_t gpio;
if (gpio_id == PWDN)
gpio = global_sensors[id].pwdn_gpio;
else if (gpio_id == RESET)
gpio = global_sensors[id].reset_gpio;
else if (gpio_id == IR_CUT0)
gpio = global_sensors[id].ir_cut_gpio[0];
else if (gpio_id == IR_CUT1)
gpio = global_sensors[id].ir_cut_gpio[1];
else if (gpio_id == IR_LED)
gpio = global_sensors[id].ir_led_gpio;
else
return -1;
if (gpio == 0xffff)
return -1;
if (status == 1) { //output
hal_gpio_set_pull(gpio, GPIO_PULL_UP);
hal_gpio_set_direction(gpio, GPIO_DIRECTION_OUTPUT);
hal_gpio_set_data(gpio, GPIO_DATA_LOW);
} else if (status == 0) {
hal_gpio_set_pull(gpio, GPIO_PULL_DOWN);
hal_gpio_set_direction(gpio, GPIO_DIRECTION_INPUT);
hal_gpio_set_data(gpio, GPIO_DATA_LOW);
} else {
hal_gpio_pinmux_set_function(gpio, GPIO_MUXSEL_DISABLED);
}
return 0;
}
int vin_gpio_get_status(int id, enum gpio_type gpio_id)
{
gpio_pin_t gpio;
int ret;
gpio_direction_t direction;
if (gpio_id == PWDN)
gpio = global_sensors[id].pwdn_gpio;
else if (gpio_id == RESET)
gpio = global_sensors[id].reset_gpio;
else if (gpio_id == IR_CUT0)
gpio = global_sensors[id].ir_cut_gpio[0];
else if (gpio_id == IR_CUT1)
gpio = global_sensors[id].ir_cut_gpio[1];
else if (gpio_id == IR_LED)
gpio = global_sensors[id].ir_led_gpio;
else
return -1;
if (gpio == 0xffff)
return -1;
ret = hal_gpio_get_direction(gpio, &direction);
vin_warn("%s(),l:%d, direction:%d\n", __func__, __LINE__, direction);
return (int)direction;
}
int vin_gpio_write(int id, enum gpio_type gpio_id, unsigned int out_value)
{
gpio_pin_t gpio;
if (gpio_id == PWDN)
gpio = global_sensors[id].pwdn_gpio;
else if (gpio_id == RESET)
gpio = global_sensors[id].reset_gpio;
else if (gpio_id == IR_CUT0)
gpio = global_sensors[id].ir_cut_gpio[0];
else if (gpio_id == IR_CUT1)
gpio = global_sensors[id].ir_cut_gpio[1];
else if (gpio_id == IR_LED)
gpio = global_sensors[id].ir_led_gpio;
else
return -1;
if (gpio == 0xffff)
return -1;
hal_gpio_set_direction(gpio, GPIO_DIRECTION_OUTPUT);
if (out_value) {
hal_gpio_set_data(gpio, GPIO_DATA_HIGH);
} else {
hal_gpio_set_data(gpio, GPIO_DATA_LOW);
}
return 0;
}
int vin_gpio_read(int id, enum gpio_type gpio_id)
{
gpio_pin_t gpio;
int ret, data;
if (gpio_id == PWDN)
gpio = global_sensors[id].pwdn_gpio;
else if (gpio_id == RESET)
gpio = global_sensors[id].reset_gpio;
else if (gpio_id == IR_CUT0)
gpio = global_sensors[id].ir_cut_gpio[0];
else if (gpio_id == IR_CUT1)
gpio = global_sensors[id].ir_cut_gpio[1];
else if (gpio_id == IR_LED)
gpio = global_sensors[id].ir_led_gpio;
else
return -1;
if (gpio == 0xffff)
return -1;
ret = hal_gpio_get_data(gpio, &data);
vin_warn("%s(),l:%d, data:%d\n", __func__, __LINE__, data);
return data;
}
int vin_set_mclk_freq(int id, unsigned long freq)
{
hal_clk_t mclk_src = 0;
int mclk_id = global_sensors[id].mclk_id;
if (freq == 24000000 || freq == 12000000 || freq == 6000000) {
mclk_src = vind_default_mclk[mclk_id].clk_24m;
} else {
mclk_src = vind_default_mclk[mclk_id].clk_pll;
}
if (hal_clk_set_parent(vind_default_mclk[mclk_id].mclk, mclk_src)) {
vin_err("set mclk%d source failed!\n", mclk_id);
return -1;
}
if (hal_clk_set_rate(vind_default_mclk[mclk_id].mclk, freq)) {
vin_err("set csi master%d clock error\n", mclk_id);
return -1;
}
vin_log(VIN_LOG_POWER, "mclk%d set rate %ld, get rate %ld\n", mclk_id,
freq, hal_clk_get_rate(vind_default_mclk[mclk_id].mclk));
return 0;
}
int vin_set_mclk(int id, unsigned int on_off)
{
struct vin_mclk_info *mclk = NULL;
int mclk_id = global_sensors[id].mclk_id;
mclk = &vind_default_mclk[mclk_id];
if (on_off && mclk->use_count++ > 0)
return 0;
else if (!on_off && (mclk->use_count == 0 || --mclk->use_count > 0))
return 0;
switch (on_off) {
case 1:
vin_log(VIN_LOG_POWER, "sensor mclk on, use_count %d!\n", mclk->use_count);
hal_gpio_pinmux_set_function(mclk->pin, mclk->pin_func[0]);
if (mclk->mclk) {
if (hal_clock_enable(mclk->mclk)) {
vin_err("csi master clock enable error\n");
return -1;
}
} else {
vin_err("csi master%d clock is null\n", mclk_id);
return -1;
}
break;
case 0:
hal_gpio_pinmux_set_function(mclk->pin, mclk->pin_func[1]);
vin_log(VIN_LOG_POWER, "sensor mclk off, use_count %d!\n", mclk->use_count);
if (mclk->mclk) {
hal_clock_disable(mclk->mclk);
} else {
vin_err("csi master%d clock is null\n", mclk_id);
return -1;
}
break;
default:
return -1;
}
return 0;
}