/* * Copyright (c) 2021-2022 Amlogic, Inc. All rights reserved. * * SPDX-License-Identifier: MIT */ #include "fd650.h" #include "common.h" #include "uart.h" #include "FreeRTOS.h" #include "timer_source.h" #include #include #include #include "mailbox-api.h" #include "vrtc.h" #include "timers.h" /* Software timer related API prototypes. */ #include "drv_errno.h" #define DRIVER_NAME "FD650" #define DEFAULT_UDELAY 3 #define ERR_FD650(errno) (DRV_ERRNO_FD650_BASE | errno) static struct fd650_bus *current_bus; static uint8_t fd650_state = FD650_STATE_TIME; static int fd650_sda_get(struct fd650_bus *bus) { int value; xGpioSetDir(bus->sda, GPIO_DIR_IN); value = xGpioGetValue(bus->sda); xGpioSetDir(bus->sda, GPIO_DIR_OUT); return value; } static void fd650_sda_set(struct fd650_bus *bus, enum GpioOutLevelType bit) { xGpioSetValue(bus->sda, bit); } static void fd650_scl_set(struct fd650_bus *bus, enum GpioOutLevelType bit) { xGpioSetValue(bus->scl, bit); } void fd650_start(struct fd650_bus *bus) { fd650_sda_set(bus, GPIO_LEVEL_HIGH); fd650_scl_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); fd650_sda_set(bus, GPIO_LEVEL_LOW); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_LOW); } void fd650_stop(struct fd650_bus *bus) { fd650_sda_set(bus, GPIO_LEVEL_LOW); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); fd650_sda_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); } void fd650_wrbyte(struct fd650_bus *bus, uint8_t dat) { uint8_t i; for (i = 0; i != 8; i++) { if (dat & 0x80) fd650_sda_set(bus, GPIO_LEVEL_HIGH); else fd650_sda_set(bus, GPIO_LEVEL_LOW); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_HIGH); dat <<= 1; udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_LOW); } fd650_sda_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_LOW); } uint8_t fd650_rdbyte(struct fd650_bus *bus) { uint8_t dat, i; fd650_sda_set(bus, GPIO_LEVEL_HIGH); dat = 0; for (i = 0; i != 8; i++) { udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); dat <<= 1; if (fd650_sda_get(bus)) dat++; fd650_scl_set(bus, GPIO_LEVEL_LOW); } fd650_sda_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_HIGH); udelay(bus->udelay); fd650_scl_set(bus, GPIO_LEVEL_LOW); return dat; } void fd650_write(struct fd650_bus *bus, uint32_t cmd) { fd650_start(bus); fd650_wrbyte(bus, ((uint8_t)(cmd >> 7) & 0x3E) | 0x40); fd650_wrbyte(bus, (uint8_t)cmd); fd650_stop(bus); } uint8_t fd650_read(struct fd650_bus *bus) { uint8_t keycode = 0; fd650_start(bus); fd650_wrbyte(bus, ((uint8_t)(FD650_GET_KEY >> 7) & 0x3E) | (0x01 | 0x40)); keycode = fd650_rdbyte(bus); fd650_stop(bus); if ((keycode & 0x00000040) == 0) keycode = 0; return keycode; } #define LEDMAPNUM 22 struct led_bitmap { uint8_t character; uint8_t bitmap; }; const struct led_bitmap bcd_decode_tab[LEDMAPNUM] = { {'0', 0x3F}, {'1', 0x06}, {'2', 0x5B}, {'3', 0x4F}, {'4', 0x66}, {'5', 0x6D}, {'6', 0x7D}, {'7', 0x07}, {'8', 0x7F}, {'9', 0x6F}, {'a', 0x77}, {'A', 0x77}, {'b', 0x7C}, {'B', 0x7C}, {'c', 0x58}, {'C', 0x39}, {'d', 0x5E}, {'D', 0x5E}, {'e', 0x79}, {'E', 0x79}, {'f', 0x71}, {'F', 0x71} }; uint8_t led_get_code(char ch) { uint8_t i, bitmap = 0x00; for (i = 0; i < LEDMAPNUM; i++) { if (bcd_decode_tab[i].character == ch) { bitmap = bcd_decode_tab[i].bitmap; break; } } return bitmap; } int32_t led_show_650(char *str, unsigned char sec_flag, unsigned char lock) { int i, iLenth; int ret; int data[4] = {0x00, 0x00, 0x00, 0x00}; struct udevice *dev; if (!current_bus) return ERR_FD650(DRV_ERROR_ACCESS); if (strcmp(str, "") == 0) return ERR_FD650(DRV_ERROR_PARAMETER); iLenth = strlen(str); if (iLenth > 4) iLenth = 4; for (i = 0; i < iLenth; i++) data[i] = led_get_code(str[i]); fd650_write(current_bus, FD650_SYSON_8); fd650_write(current_bus, FD650_DIG0 | (uint8_t)data[0] | FD650_DOT); if (sec_flag) fd650_write(current_bus, FD650_DIG1 | (uint8_t)data[1] | FD650_DOT); else fd650_write(current_bus, FD650_DIG1 | (uint8_t)data[1]); if (lock) fd650_write(current_bus, FD650_DIG2 | (uint8_t)data[2] | FD650_DOT); else fd650_write(current_bus, FD650_DIG2 | (uint8_t)data[2]); fd650_write(current_bus, FD650_DIG3 | (uint8_t)data[3] | FD650_DOT); return 0; } static void *prvFD650GetInfo(void *msg) { uint8_t data[5] = {0}; uint8_t state = *(((uint8_t *)msg)); int colon_on = *(((uint8_t *)msg) + 1); switch (state) { case FD650_STATE_SHOW: data[0] = *(((uint8_t *)msg) + 2); data[1] = *(((uint8_t *)msg) + 3); data[2] = *(((uint8_t *)msg) + 4); data[3] = *(((uint8_t *)msg) + 5); led_show_650(data, colon_on, 1); fd650_state = FD650_STATE_SHOW; break; case FD650_STATE_TIME: fd650_state = FD650_STATE_TIME; break; default: break; } /* end switch */ return NULL; } static void fd650ShowTime(TimerHandle_t xTimer) { char str[5]; if (fd650_state == FD650_STATE_TIME) { vPoweroffGetRtcMinSec(str); led_show_650(str, 1, 1); } } int fd650_bus_init(uint32_t id) { TimerHandle_t xFD650Timer = NULL; int ret; current_bus = &fd650_plat_data[id]; xPinmuxSet(current_bus->sda, PIN_FUNC0); xPinmuxSet(current_bus->scl, PIN_FUNC0); xGpioSetDir(current_bus->sda, GPIO_DIR_OUT); xGpioSetDir(current_bus->scl, GPIO_DIR_OUT); xGpioSetValue(current_bus->sda, GPIO_LEVEL_LOW); xGpioSetValue(current_bus->scl, GPIO_LEVEL_LOW); fd650_sda_set(current_bus, GPIO_LEVEL_HIGH); fd650_scl_set(current_bus, GPIO_LEVEL_HIGH); udelay(100); ret = xInstallRemoteMessageCallbackFeedBack(REE2AO_CHANNEL, MBX_CMD_GET_FD650_INFO, prvFD650GetInfo, 1); if (ret == MBOX_CALL_MAX) return -pdFREERTOS_ERRNO_EINVAL; /* creat fd650 timer */ xFD650Timer = xTimerCreate("Timer", pdMS_TO_TICKS(500), pdTRUE, NULL, fd650ShowTime); iprintf("%s: Starting fd650 task ...\n", DRIVER_NAME); xTimerStart(xFD650Timer, 0); }