diff options
author | Kevin | 2014-11-15 11:48:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 11:48:36 +0800 |
commit | d04075478d378d9e15f3e1abfd14b0bd124077d4 (patch) | |
tree | 733dd964582f388b9e3e367c249946cd32a2851f /common/wmt_display | |
download | FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2 FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip |
init commit via android 4.4 uboot
Diffstat (limited to 'common/wmt_display')
63 files changed, 27410 insertions, 0 deletions
diff --git a/common/wmt_display/animation/charge_animation.c b/common/wmt_display/animation/charge_animation.c new file mode 100755 index 0000000..7728002 --- /dev/null +++ b/common/wmt_display/animation/charge_animation.c @@ -0,0 +1,1262 @@ +/*******************************************************************************
+* Copyright (c) 2013 WonderMedia Technologies, Inc.
+*
+* Abstract:
+* This program is designed to show the charge animation
+*
+******************************Release History ***********************************
+*
+* Version 1.0 , HowayHuo, 2013/5/8
+* First version: Created by Howayhuo
+*
+**********************************************************************************/
+#include <common.h>
+#include <command.h>
+#include <asm/arch/common_def.h>
+#include <asm/byteorder.h>
+#include <bmp_layout.h>
+#include "../../../board/wmt/include/wmt_pmc.h"
+#include "../../../board/wmt/wmt_battery/wmt_battery.h"
+#include "../minivgui.h"
+#include "../wmt_display.h"
+
+#define HSP3_STATUS (0xD8130000 + 0x3C)
+#define REBOOT_BIT 0x10
+
+#define POWERUP_SOURCE_STATUS (0xD8130000 + 0xD0)
+#define PWRBTN_BIT 0x01
+#define VBAT_RISING_BIT 0x02
+#define DCDET_RISING_BIT 0x04
+#define DCDET_FALLING_BIT 0x08
+#define DCDET_BIT 0x10
+
+#define ENV_MPTOOL_DETECT "wmt.mptool.detect"
+#define ENV_MPTOOL_TIMEOUT "wmt.mptool.timeout"
+#define ENV_USBPC_TIMEOUT "wmt.usbpc.timeout"
+
+static unsigned char *sp_mem_addr = (unsigned char *)0x3000000;
+
+static int s_usb_to_pc;
+static int s_pwm_duty_decreased;
+static int s_battery_init_ok = -1;
+static int s_animation_init_ok = -1;
+static int s_lcd_first_light = 1;
+
+/*
+s_step_by_step_light value:
+1: the backlight is light step by setp.
+0: the backlight is light right now
+*/
+static int s_step_by_step_light = 1;
+
+extern int g_tf_boot;
+
+//extern char* CMD_LOAD_SCRIPT;
+extern int g_show_logo;
+extern int udc_fastboot_init(void);
+extern void udc_fastboot_transfer(void);
+extern void udc_fastboot_exit(void);
+extern int wmt_udc_connected(void);
+extern int udc_fastboot_is_init(void);
+extern void do_wmt_poweroff(void);
+extern int wmt_mptool_ready(void);
+extern int usb_plugin(void);
+extern void run_fastboot(int backlight_on);
+
+extern struct nand_chip *get_current_nand_chip(void);
+extern int WMTAccessNandEarier(unsigned long long naddr, unsigned int maddr,
+ unsigned int size, int write);
+
+extern unsigned int pwm_get_enable(int no);
+extern void lcd_blt_enable(int no, int enable);
+extern void lcd_set_power_down(int enable);
+//extern void hint_battery_checking(void);
+
+static int sleep_sec(int sec)
+{
+ ulong start = get_timer(0);
+ ulong delay;
+
+ delay = sec * CFG_HZ;
+
+ while (get_timer(start) < delay) {
+ if (ctrlc ()) {
+ return (-1);
+ }
+ udelay (100);
+ }
+
+ return 0;
+}
+
+//return level ( 0 ~ 5 ), level < 0 is error
+static int get_battery_level(int *p_percent)
+{
+ int capacity, level = 0;
+
+ if (wmt_battery_is_charging_full() == 1) {
+ printf("power is full\n");
+ capacity = 100;
+ } else
+ capacity = wmt_battery_get_capacity();
+
+ *p_percent = capacity;
+
+ if (capacity >= 0 && capacity <= 100)
+ level = capacity / 20;
+
+ return level;
+}
+
+static void decrease_pwm_duty(int duty_percent)
+{
+ int duty;
+
+ if(!(g_display_vaild & DISPLAY_ENABLE))
+ return;
+
+ //if(s_pwm_duty_decreased == 1)
+ // return;
+
+ if (g_display_param.vout == VPP_VOUT_LCD) {
+ if ((g_display_vaild & PWMDEFMASK) == PWMDEFTP) {
+ if(duty_percent <= g_pwm_setting.duty) {
+ lcd_blt_set_pwm(g_pwm_setting.pwm_no,
+ duty_percent, g_pwm_setting.period);
+
+ s_pwm_duty_decreased = 1;
+
+ mdelay(10);
+ }
+ } else {
+ duty = (duty_percent * g_pwm_setting.period) / 100;
+ if(duty <= g_pwm_setting.duty) {
+ pwm_set_duty(g_pwm_setting.pwm_no, duty - 1);
+
+ s_pwm_duty_decreased = 1;
+
+ mdelay(10);
+ }
+ }
+ }
+}
+
+static void restore_pwm_duty(void)
+{
+ if(s_pwm_duty_decreased == 0)
+ return;
+
+ if(!(g_display_vaild & DISPLAY_ENABLE))
+ return;
+
+ if (g_display_param.vout == VPP_VOUT_LCD) {
+ if ((g_display_vaild & PWMDEFMASK) == PWMDEFTP) {
+ lcd_blt_set_pwm(g_pwm_setting.pwm_no,
+ g_pwm_setting.duty, g_pwm_setting.period);
+ } else {
+ pwm_set_duty(g_pwm_setting.pwm_no,
+ g_pwm_setting.duty - 1);
+ }
+ }
+
+ s_pwm_duty_decreased = 0;
+}
+
+static void set_lcd_backlight(int on)
+{
+ int duty, i = 0;
+ int charger_type;
+
+ if(on) {
+ charger_type = wmt_charger_cable_type();
+ if((charger_type == CABLE_TYPE_USB) && s_usb_to_pc && !wmt_charger_pc_charging()) {
+ if(wmt_battery_is_lowlevel() > 0)
+ decrease_pwm_duty(30);
+ else
+ restore_pwm_duty();
+ }
+
+ if(s_lcd_first_light) {
+ if(!(REG32_VAL(HSP3_STATUS) & REBOOT_BIT)
+ && !wmt_is_dc_plugin()
+ && !(REG8_VAL(POWERUP_SOURCE_STATUS) & PWRBTN_BIT)) {
+ printf("Adapter is removed when open lcd backlight.\nPower off\n");
+ do_wmt_poweroff();
+ }
+ s_lcd_first_light = 0;
+ }
+
+ if(s_step_by_step_light) {
+ decrease_pwm_duty(30);
+ duty = 30;
+ lcd_blt_enable(g_pwm_setting.pwm_no, 1);
+ while(duty < g_pwm_setting.duty) {
+ mdelay(20);
+ duty = 40 + 5 * i;
+ i++;
+ decrease_pwm_duty(duty);
+ }
+ } else
+ lcd_blt_enable(g_pwm_setting.pwm_no, 1);
+ } else
+ lcd_blt_enable(g_pwm_setting.pwm_no, 0);
+}
+
+static void low_battery_picture_show(void)
+{
+ //clear_charge_percent(sp_mem_addr);
+ mv_clearFB();
+ show_charge_picture(sp_mem_addr, 6);
+}
+
+static void update_current_battery_picture(void)
+{
+ int index, percent;
+
+ if(wmt_battery_is_lowlevel() > 0)
+ low_battery_picture_show();
+ else {
+ index = get_battery_level(&percent);
+ if(index >= 0) {
+ display_charge_percent(sp_mem_addr, percent);
+ show_charge_picture(sp_mem_addr, index);
+ }
+ }
+}
+
+static int charge_animation_init(void)
+{
+ int ret;
+ unsigned int nand_addr;
+ char *s, *s_logosize_uboot, *s_logosize_charge;
+ unsigned int logo_size, total_size;
+
+ //printf("charging animation init\n");
+
+ if(s_animation_init_ok == 0)
+ return -1;
+ else if(s_animation_init_ok == 1)
+ return 0;
+
+ if(!g_tf_boot) {
+ //1: check nand flash env
+ s = getenv("wmt.nfc.mtd.u-boot-logo");
+ if(s == NULL) {
+ printf("wmt.nfc.mtd.u-boot-logo isn't set\n");
+ s_animation_init_ok = 0;
+ return -1;
+ } else {
+ nand_addr = simple_strtoul (s, NULL, 16);
+
+ total_size = 0;
+ s_logosize_uboot = getenv("wmt.logosize.uboot");
+ if(s_logosize_uboot) {
+ s_logosize_charge = getenv("wmt.logosize.charge");
+ if(s_logosize_charge)
+ total_size = simple_strtoul(s_logosize_uboot, NULL, 0)
+ + simple_strtoul(s_logosize_charge, NULL, 0);
+ }
+
+ if(total_size == 0)
+ total_size = 0x380000;
+
+ printf("anim init: nand_addr = 0x%x, mem_addr = 0x%x, read_size = 0x%x\n",
+ nand_addr, (unsigned int)sp_mem_addr, total_size);
+
+ REG32_VAL(GPIO_BASE_ADDR + 0x200) &= ~(1 << 11); //PIN_SHARE_SDMMC1_NAND
+ ret = WMTAccessNandEarier(nand_addr, (unsigned int)sp_mem_addr, total_size, 0);
+ if(ret) {
+ printf("load charge-anim fail\n");
+ s_animation_init_ok = 0;
+ return -1;
+ }
+ }
+
+ //2: check bmp header
+ if(*sp_mem_addr != 'B') {
+ printf("logo isn't BMP format\n");
+ s_animation_init_ok = 0;
+ return -1;
+ }
+
+ logo_size = (*(unsigned short *)(sp_mem_addr + 4) << 16) + (*(unsigned short *)(sp_mem_addr + 2));
+
+ if(*(sp_mem_addr + logo_size) != 'B') {
+ printf("charge-anim isn't BMP format\n");
+ s_animation_init_ok = 0;
+ return -1;
+ }
+ } else {
+ ret = run_command("mmcinit 1", 0);
+ if(ret == -1) {
+ printf("TF: run \"mmcinit 1\" failed\n");
+ s_animation_init_ok = 0;
+ return -1;
+ } else {
+ char tmp[100] = {0};
+ sprintf(tmp, "fatload mmc 1 0x%x charge-logo.bmp", (unsigned int)sp_mem_addr);
+ ret = run_command(tmp, 0);
+ if(ret == -1) {
+ printf("TF: fatload charge-logo.bmp failed\n");
+ s_animation_init_ok = 0;
+ return -1;
+ }
+ }
+
+ if(*sp_mem_addr != 'B') {
+ printf("TF: charge-anim isn't BMP format\n");
+ s_animation_init_ok = 0;
+ return -1;
+ }
+ }
+
+ s_animation_init_ok = 1;
+
+ printf("load charge-animation ok\n");
+
+ return 0;
+}
+
+/*
+static int need_battery_adjust(void)
+{
+ char *s;
+
+ s = getenv("wmt.battery.adjust");
+ if((s != NULL) && !strcmp(s, "0")) {
+ return 0;
+ }
+
+ return 1;
+
+}
+*/
+
+static int battery_init(void)
+{
+ int ret;
+
+ if(s_battery_init_ok == 0)
+ return -1;
+ else if(s_battery_init_ok == 1)
+ return 0;
+
+ ret = wmt_power_supply_init();
+ if(ret) {
+ printf("battery init error\n");
+ s_battery_init_ok = 0;
+ return -1;
+ }
+
+ s_battery_init_ok = 1;
+
+ return 0;
+}
+
+int low_power_detect(void)
+{
+ int ret;
+ int delay;
+
+ if(wmt_is_dc_plugin())
+ return 0;
+
+ ret = battery_init();
+ if(ret) {
+ printf("battery init error. Skip Low power detect\n");
+ return -1;
+ }
+
+ printf("check whether low power or not\n");
+
+ ret = wmt_battery_is_lowlevel();
+ if(ret < 0) {
+ printf("check battery low failed\n");
+ return -1;
+ } else if(ret == 0) {
+ //printf("battery power enough\n");
+ return 0;
+ } else {
+ printf("low power detected\n");
+ }
+
+ if(wmt_battery_is_gauge() == 1)
+ delay = 3;
+ else
+ delay = 60;
+
+ while(delay) {
+ if(delay % 10 == 0) {
+ if (tstc()) {
+ if (getc() == 0xd) {
+ printf("Got 'Enter' key. Cancel Low power detect\n");
+ g_show_logo = 1;
+ return 0;
+ }
+ }
+ }
+
+ if(wmt_is_dc_plugin()) {
+ printf("Detected adapter plugin. Cancel Low power detect\n");
+ break;
+ }
+
+ mdelay(50);
+
+ ret = wmt_battery_is_lowlevel();
+ if(ret < 0) {
+ restore_pwm_duty();
+ printf("check battery low failed\n");
+ break;
+ } else if(ret == 0) {
+ restore_pwm_duty();
+ printf("battery power enough\n");
+ break;
+ }
+
+ delay--;
+ }
+
+ //printf("low power detect complete\n");
+
+ //display low power picture
+ if(delay == 0) {
+ if (!(g_display_vaild & DISPLAY_ENABLE)) {
+ ret = display_init(0, 0);
+ if(ret == -1) {
+ printf("Display init fail. Skip Low power detect\n");
+ return -1;
+ }
+ }
+ charge_animation_init();
+ low_battery_picture_show();
+ decrease_pwm_duty(30);
+ set_lcd_backlight(1);
+
+ delay = 500;
+ while(delay) {
+ if(delay % 100 == 0) {
+ if (tstc()) {
+ if (getc() == 0xd) {
+ printf("Got 'Enter' key. Cancel Low power picture display\n");
+ g_show_logo = 1;
+ return 0;
+ }
+ }
+ }
+
+ if(wmt_is_dc_plugin()) {
+ printf("Detected adapter plugin. Cancel Low power picture display\n");
+ return 0;
+ }
+
+ mdelay(10);
+ delay--;
+ }
+
+ set_lcd_backlight(0);
+ lcd_set_power_down(1);
+ mdelay(500); //delay for avoiding lcd blink
+ printf("----> low power. power off\n");
+ do_wmt_poweroff();
+ }
+
+ return 0;
+}
+
+#define TIMEOUT_USBPC_CHECK 400 // 400 ms
+#define TIMEOUT_MPTOOL_CHECK 3000 // 3 s
+
+/*
+* Function: check_udc_to_pc
+*
+* Return:
+* 1: usb device connect to pc
+* 0: udc device doesn't connect to pc
+* <0: error
+*/
+int check_udc_to_pc(int force)
+{
+ int ret, delay_check_connected;
+ static int udc_had_check;
+ static int check_result;
+ unsigned int timeout;
+ char *s;
+
+ if(force)
+ udc_had_check = 0;
+
+ if(udc_had_check == 1)
+ return check_result;
+
+ udc_had_check = 1;
+
+ if(!usb_plugin()) {
+ printf("check_udc_to_pc: usb plugout\n");
+ s_usb_to_pc = 0;
+ check_result = 0;
+ return 0;
+ } else
+ printf("check_udc_to_pc: usb plugin\n");
+
+ s = getenv(ENV_USBPC_TIMEOUT);
+ if(s) {
+ timeout = simple_strtoul(s, NULL, 0);
+ printf("Manually set usbpc timeout: %u ms\n", timeout);
+ } else
+ timeout = TIMEOUT_USBPC_CHECK;
+
+ if(timeout > 300000) {
+ printf("usbpc timeout force change to 300000 ms\n");
+ timeout = 300000;
+ }
+
+ if(!udc_fastboot_is_init()) {
+ ret = udc_fastboot_init();
+ if(ret) {
+ printf("udc_fastboot_init error. check_udc_to_pc fail\n");
+ s_usb_to_pc = 0;
+ check_result = -1;
+ return -1;
+ }
+ }
+
+ delay_check_connected = 0;
+
+ while(1) {
+ udc_fastboot_transfer();
+ if(wmt_udc_connected()) {
+ printf("usb connect to pc, detect_time = %d ms\n", delay_check_connected);
+ s_usb_to_pc = 1;
+ check_result = 1;
+ return 1;
+ }
+
+ if(delay_check_connected >= timeout)
+ break;
+
+ delay_check_connected++;
+
+ if (tstc()) {
+ if(getc() == 0x0d) {
+ printf("Got 'Enter'. Cancel usbpc check. check time: %d ms\n", delay_check_connected);
+ break;
+ }
+ }
+
+ mdelay(1);
+ }
+
+ if(delay_check_connected >= timeout)
+ printf("usb doesn't connect to pc\n");
+
+ s_usb_to_pc = 0;
+ check_result = 0;
+ return 0;
+}
+
+/*
+* Function: check_mptool
+*
+* Return:
+* 1: mptool is detected
+* 0: mptool is NOT detected
+* <0: mptool checking is cancel
+*/
+int check_mptool(void)
+{
+ char *s;
+ int ret, delay_check_mptool;
+ unsigned int timeout;
+
+ if((s = getenv(ENV_MPTOOL_DETECT)) != NULL && !strcmp(s, "0"))
+ return 0;
+
+ if(s_usb_to_pc == 0)
+ return 0;
+
+ s = getenv(ENV_MPTOOL_TIMEOUT);
+ if(s) {
+ timeout = simple_strtoul(s, NULL, 0);
+ printf("Manually set mptool timeout: %u ms\n", timeout);
+ } else
+ timeout = TIMEOUT_MPTOOL_CHECK;
+
+ if(timeout > 600000) {
+ printf("mptool timeout force change to 600000 ms\n");
+ timeout = 600000;
+ }
+
+ if(!udc_fastboot_is_init()) {
+ ret = udc_fastboot_init();
+ if(ret) {
+ printf("udc_fastboot_init error. check mptool fail\n");
+ return 0;
+ }
+ }
+
+ delay_check_mptool = 0;
+
+ printf("Hint: Press 'Enter' key to Cancel MPTool detection\n");
+ while(1) {
+ udc_fastboot_transfer();
+ if(wmt_mptool_ready()) {
+ printf("MPTool is detected\n");
+ return 1;
+ }
+
+ if(delay_check_mptool >= timeout)
+ break;
+
+ delay_check_mptool++;
+
+ if (tstc()) {
+ switch(getc()) {
+ case 0x03:
+ printf("Got 'Ctrl+C'. Cancel mptool check. check time: %d ms\n", delay_check_mptool);
+ return -1;
+
+ // we think the mptool is not found when pressing 'Enter' key
+ case 0x0d:
+ printf("Got 'Enter'. Cancel mptool check. check time: %d ms\n", delay_check_mptool);
+ return 0;
+
+ default:
+ break;
+ }
+ }
+
+ mdelay(1);
+ }
+
+ if(delay_check_mptool >= timeout)
+ printf("MPTool is NOT detected\n");
+
+ return 0;
+}
+
+int set_charge_current(void)
+{
+ int ret, usb_to_pc;
+
+ ret = battery_init();
+ if(ret) {
+ printf("battery_init error. set_charge_current fail\n");
+ return -1;
+ }
+
+ if(wmt_is_dc_plugin()) {
+ if(wmt_charger_cable_type() == CABLE_TYPE_USB) {
+ usb_to_pc = check_udc_to_pc(0);
+ if(usb_to_pc == 0) {
+ printf("usb_adapter plugin. set large current charge\n");
+ wmt_charger_event_callback(POWER_EVENT_DCDET_ADAPTER);
+ } else if(usb_to_pc == 1)
+ printf("usb connect to pc. default small current charge\n");
+ else {
+ printf("check usb_to_pc fail. set large current charge");
+ wmt_charger_event_callback(POWER_EVENT_DCDET_ADAPTER);
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void check_pmc_busy(void)
+{
+ while (PMCS2_VAL & 0x3F0038)
+ ;
+}
+
+static void set_arm_freq(int freq)
+{
+ auto_pll_divisor(DEV_ARM, CLK_ENABLE, 0, 0);
+ auto_pll_divisor(DEV_ARM, SET_PLLDIV, 2, freq);
+ check_pmc_busy();
+}
+
+#define PERIOD_CHECK 10 // 10 ms //how long time to check
+#define PERIOD_PLAY 250 // 250 ms //the play speed
+#define PERIOD_PAUSE 700 // 700 ms //the pause time after a play peroid complete
+#define PERIOD_DETECTADAPT 50 // 50 ms //check if the power adapter is unplug
+#define PERIOD_READBATT 1 * 1000 // 1 s //how long time to read battery
+#define PERIOD_READPWRKEY 10 // 10ms //how long time to detect power key
+#define PERIOD_LONGPRESS 500 // 500 ms //how long time is regarded as long press
+#define PERIOD_BLTIMEOUT 10 * 1000 // 10 s //how long time to close backlight
+#define PERIOD_USBDETECT 50 // 50 ms //how long time to detect usb
+#define PERIOD_GAUGE_READBATT 10 * 1000 // 10 s //how long time to read battery
+
+/*
+* play_charge_animation()
+* return:
+* 0: play charging animation success
+* 1: fail to play charging animation. need detect low power
+* <0: fail to play charging animation. needn't detect low power
+*/
+int play_charge_animation(void)
+{
+ const int max_play_count = (PERIOD_PLAY) / (PERIOD_CHECK);
+ const int max_pause_count = (PERIOD_PAUSE - PERIOD_PLAY) / (PERIOD_CHECK);
+ const int max_detectAdapter_count = (PERIOD_DETECTADAPT) / (PERIOD_CHECK);
+ int max_readBatt_count = (PERIOD_READBATT) / (PERIOD_CHECK);
+ const int max_readPwrKey_count = (PERIOD_READPWRKEY) / (PERIOD_CHECK);
+ const int max_longPress_count = (PERIOD_LONGPRESS) / (PERIOD_CHECK);
+ const int max_blTimeout_count = (PERIOD_BLTIMEOUT) / (PERIOD_CHECK);
+ const int max_usbDetect_count = (PERIOD_USBDETECT) / (PERIOD_CHECK);
+
+ int play_count; //play period
+ int pause_count; //pause time after a play period complete
+ int detectAdapter_count; //check if the adapter is unpluged
+ int readBatt_count; //how long time to read battery
+ int readPwrKey_count; //how long time to detect power key
+ int longPress_count; //how long time is regarded as long press
+ int blTimeout_count; //how long time to close backlight
+ int usbDetect_count; //how long time to detect usb
+
+ int frame_num, frame_index, start_index, backup_start_index;
+ int is_powerKey_press, backup_pwm_status;
+
+ int battery_is_full = 0, udc_is_init;
+ int ret;
+ char *s;
+ int charger_type = CABLE_TYPE_UNKNOWN;
+ int percent;
+ int delay;
+ int saved_arm_freq;
+ int full_event_sended = 0;
+ int is_charging = 1;
+ int is_usb_plugin = 0;
+ int need_check_mptool;
+ //int current_arm_freq;
+ //printf("play charging animation\n");
+
+ //1: detect "enter key"
+ if (tstc()) {
+ if (getc() == 0xd) { // "Enter" key
+ puts("Got 'Enter' key. Cancel charge animation play\n");
+ return 0;
+ }
+ }
+
+ // 2: check power source
+ if(!wmt_is_dc_plugin() && !(REG8_VAL(POWERUP_SOURCE_STATUS) & PWRBTN_BIT)) {
+ printf("Adatper is removed when init charging-animation.\nPower off\n");
+ do_wmt_poweroff();
+ }
+
+ //3: detect power key press
+ if(PMPB_VAL & BIT24) {
+ printf("Power key detected. Skip charge-anim play\n");
+ return 1;
+ }
+
+ //4: check power on by reset
+ if((REG32_VAL(HSP3_STATUS) & REBOOT_BIT) == REBOOT_BIT) {
+ printf("system Reboot. Skip charge-anim play\n");
+ return 1;
+ }
+
+ //5: check charge animation env
+ s = getenv(ENV_CHARGE_ANIMATION);
+ if((s != NULL) && !strcmp(s, "0")) //if wmt.display.chargeanim is set to 0
+ return 1;
+
+ //6: check dircect boot env
+ if(((s = getenv("wmt_sys_directboot")) != NULL && !strcmp(s, "1")) \
+ || ((s = getenv("wmt_sys_restore")) != NULL && !strcmp(s, "1")))
+ return 1;
+
+
+ //7: battery init
+ ret = battery_init();
+ if(ret) {
+ printf("battery init error. Don't play charge-anim\n");
+ return -1;
+ }
+
+ if(wmt_battery_is_gauge() == 1) {
+ printf("battery is gauge\n");
+ max_readBatt_count = (PERIOD_GAUGE_READBATT) / (PERIOD_CHECK);
+ }
+
+ //printf("REG32_VAL(PM_CTRL_BASE_ADDR + 0x00D0) = 0x%x\n", REG8_VAL(PM_CTRL_BASE_ADDR + 0xd0));
+
+ //8: lcd init. but don't open backlight
+ s = getenv("wmt.backlight.stepbystep"); //if wmt.backlight.stepbystep is set to 0
+ if((s != NULL) && !strcmp(s, "0"))
+ s_step_by_step_light = 0;
+
+ if (!(g_display_vaild & DISPLAY_ENABLE)) {
+ ret = display_init(0, 0);
+ if(ret == -1) {
+ printf("Display init fail. Don't play charge-anim\n");
+ return -1;
+ }
+ }
+ mv_clearFB();
+
+ //9: check adapter
+ charger_type = wmt_charger_cable_type();
+
+ if(wmt_is_dc_plugin()) {
+ if(charger_type == CABLE_TYPE_DC)
+ printf("AC charger plugin\n");
+ else if(charger_type == CABLE_TYPE_USB) {
+ printf("usb plugin\n");
+ } else {
+ printf("charger type error. Don't play charge-anim\n");
+ return -1;
+ }
+ } else {
+ printf("Battery power supply\n");
+ if((REG8_VAL(POWERUP_SOURCE_STATUS) & PWRBTN_BIT) == 0) {
+ printf("POWERUP_SOURCE_STATUS = 0x%x\n", REG8_VAL(POWERUP_SOURCE_STATUS));
+ printf("Adatper is removed when start play charging-animation.\nPower off\n");
+ do_wmt_poweroff();
+ }
+ low_power_detect();
+ if(!wmt_is_dc_plugin())
+ return -1;
+
+ // when using usb charge, if plugin adapter during low_power_detect, re-check udc to pc
+ if(charger_type == CABLE_TYPE_USB) {
+ printf("check if usb connect to pc\n");
+ if(!udc_fastboot_is_init()) {
+ ret = udc_fastboot_init();
+ if(ret) {
+ printf("udc_fastboot_init error. Don't play charge-anim\n");
+ return -1;
+ }
+ }
+ check_udc_to_pc(1);
+ set_charge_current();
+ if(s_usb_to_pc == 0)
+ restore_pwm_duty();
+ }
+ }
+
+ //10: charge animation init
+ ret = charge_animation_init();
+ if(ret) {
+ printf("charge-anim init fail. Don't play charge-anim\n");
+ return -1;
+ }
+
+ //11: get battery level
+ start_index = get_battery_level(&percent);
+ if(start_index < 0) {
+ printf("Battery level error(%d). Don't play charge-anim\n", start_index);
+ return -1;
+ }
+
+ printf("Hit 'Enter' key to stop animation\n");
+
+ //12: show the first charge picture
+ frame_num = 6;
+ play_count = -1;
+ pause_count = 0;
+ detectAdapter_count = 0;
+ readBatt_count = 0;
+ readPwrKey_count = 0;
+ longPress_count = -1;
+ is_powerKey_press = 0;
+ backup_pwm_status = 0;
+ blTimeout_count = 0;
+ usbDetect_count = 0;
+
+ frame_index = start_index;
+
+ init_charge_percent();
+ //display_charge_percent(sp_mem_addr, percent);
+ show_charge_picture(sp_mem_addr, frame_index);
+
+ if(start_index != frame_num - 1) //not last frame
+ frame_index++;
+
+ //13: when using usb charge, detect low power if usb connect to pc
+ if((charger_type == CABLE_TYPE_USB) && s_usb_to_pc && !wmt_charger_pc_charging()) {
+ ret = wmt_battery_is_lowlevel();
+ if(ret > 0) {
+ printf("USB connect to PC. Low power\n");
+
+ if(wmt_battery_is_gauge() == 1)
+ delay = 3;
+ else
+ delay = 60;
+
+ while(delay) {
+ if (tstc()) {
+ if (getc() == 0xd) {
+ printf("Got 'Enter' key. Cancel Low power detect during USB connect to PC\n");
+ return 0;
+ }
+ }
+
+ if(!wmt_is_dc_plugin()) {
+ low_battery_picture_show();
+ decrease_pwm_duty(30);
+ set_lcd_backlight(1);
+ sleep_sec(5);
+ set_lcd_backlight(0);
+ lcd_set_power_down(1);
+ mdelay(500); //delay for avoiding lcd blink
+ printf("----> USB connect to PC. Low power. power off\n");
+ do_wmt_poweroff();
+ }
+
+ mdelay(50);
+
+ ret = wmt_battery_is_lowlevel();
+ if(ret < 0) {
+ printf("Low power detect failed during USB connect to PC\n");
+ return -1;
+ } else if(ret == 0) {
+ printf("battery power enough during USB connect to PC\n");
+ break;
+ }
+
+ delay--;
+ }
+
+ if(delay == 0)
+ low_battery_picture_show();
+
+ } else if(ret < 0) {
+ printf("Low power detect failed during USB connect to PC\n");
+ return -1;
+ } else
+ printf("USB connect to PC. Power enough\n");
+
+ set_lcd_backlight(1);
+ } else
+ set_lcd_backlight(1);
+
+ //14: set cpu freq to 300MHz
+ saved_arm_freq = auto_pll_divisor(DEV_ARM, GET_FREQ, 0, 0);
+ //printf("save cpu freq = %d\n", saved_arm_freq);
+ set_arm_freq(300);
+ //current_arm_freq = auto_pll_divisor(DEV_ARM, GET_FREQ, 0, 0);
+ //printf("set cpu freq = %d\n", current_arm_freq);
+
+ //15: set charge current and control led
+ if (charger_type == CABLE_TYPE_DC) {
+ wmt_charger_event_callback(POWER_EVENT_DCDET_ADAPTER);
+ } else if (charger_type == CABLE_TYPE_USB) {
+ if (s_usb_to_pc == 1)
+ wmt_charger_event_callback(POWER_EVENT_DCDET_USBPC);
+ else
+ wmt_charger_event_callback(POWER_EVENT_DCDET_ADAPTER);
+ }
+
+ if(usb_plugin()) {
+ printf("usb plugin before charging\n");
+ is_usb_plugin = 1;
+ } else {
+ printf("usb plugout before charging\n");
+ is_usb_plugin = 0;
+ }
+
+ //16: check whether detect mptool or not
+ if((s = getenv(ENV_MPTOOL_DETECT)) != NULL && !strcmp(s, "0"))
+ need_check_mptool = 0;
+ else
+ need_check_mptool = 1;
+
+ //17: enter the animation loop
+ while(1) {
+ if (tstc()) {//we got a key press
+ printf("we got a key press\n");
+ //Check if the key is 'Enter' which ascii code is 13
+ // If the key is 'Enter', exit
+ if (getc() == 13)
+ break;
+ }
+
+ //check if usb connect to pc. And check mptool when usb connect to pc
+ if(need_check_mptool) {
+ if(usbDetect_count >= 0)
+ usbDetect_count++;
+
+ if(usbDetect_count > max_usbDetect_count) {
+ if(usb_plugin()) {
+ if(is_usb_plugin == 0) {
+ is_usb_plugin = 1;
+ printf("usb plugin during charging\n");
+ }
+
+ if(!udc_fastboot_is_init()) {
+ ret = udc_fastboot_init();
+ if(ret) {
+ printf("udc_fastboot_init error during playing charge-anim\n");
+ udc_is_init = 0;
+ } else
+ udc_is_init = 1;
+ } else
+ udc_is_init = 1;
+ } else {
+ if(is_usb_plugin == 1) {
+ is_usb_plugin = 0;
+ printf("usb plugout during charging\n");
+ }
+ udc_fastboot_exit();
+ udc_is_init = 0;
+ if(s_usb_to_pc) {
+ s_usb_to_pc = 0;
+ if(charger_type == CABLE_TYPE_USB && wmt_is_dc_plugin())
+ wmt_charger_event_callback(POWER_EVENT_DCDET_ADAPTER);
+ }
+ }
+
+ if(udc_is_init) {
+ udc_fastboot_transfer();
+ if(s_usb_to_pc == 0) {
+ if(wmt_udc_connected()) {
+ printf("usb connect to pc\n");
+ s_usb_to_pc = 1;
+ if(charger_type == CABLE_TYPE_USB) {
+ wmt_charger_event_callback(POWER_EVENT_DCDET_USBPC);
+ if(!wmt_charger_pc_charging())
+ update_current_battery_picture();
+ }
+ }
+ } else {
+ if(wmt_mptool_ready()) {
+ set_arm_freq(saved_arm_freq / 1000000);
+ udc_fastboot_exit();
+ run_fastboot(1);
+ break;
+ }
+ }
+ }
+
+ usbDetect_count = 0;
+ }
+ }
+
+ if((charger_type == CABLE_TYPE_USB) && s_usb_to_pc && !wmt_charger_pc_charging())
+ is_charging = 0;
+ else
+ is_charging = 1;
+
+ readBatt_count++;
+ readPwrKey_count++;
+ detectAdapter_count++;
+
+ if(longPress_count >= 0)
+ longPress_count++;
+
+ if(blTimeout_count >= 0)
+ blTimeout_count++;
+
+ if(detectAdapter_count > max_detectAdapter_count) {
+ detectAdapter_count = 0;
+ if(!wmt_is_dc_plugin()) {
+ if(is_charging) {
+ display_charge_percent(sp_mem_addr, percent);
+ show_charge_picture(sp_mem_addr, start_index);
+ }
+
+ printf("unplug power adapter\n");
+ if(!pwm_get_enable(g_pwm_setting.pwm_no)) {
+ set_lcd_backlight(1);
+ if(is_charging == 0)
+ update_current_battery_picture();
+ }
+
+ wmt_charger_event_callback(POWER_EVENT_DCDET_PLUGOUT);
+ sleep_sec(3);
+ set_lcd_backlight(0);
+ lcd_set_power_down(1);
+ mdelay(500); //delay for avoiding lcd blink
+ printf("power off\n");
+ do_wmt_poweroff();
+ }
+ }
+
+ if(readBatt_count > max_readBatt_count) {
+ readBatt_count = 0;
+ backup_start_index = start_index;
+ start_index = get_battery_level(&percent);
+
+ if (percent == 100 && is_charging) {
+ if (!full_event_sended) {
+ wmt_charger_event_callback(POWER_EVENT_CHARGING_FULL);
+ full_event_sended = 1;
+ }
+ } else
+ full_event_sended = 0;
+
+ if(start_index < 0 || start_index >= frame_num) {
+ if(is_charging) {
+ display_charge_percent(sp_mem_addr, percent);
+ show_charge_picture(sp_mem_addr, backup_start_index);
+ }
+ printf("read battery error\n");
+ if(!pwm_get_enable(g_pwm_setting.pwm_no)) {
+ set_lcd_backlight(1);
+ if(is_charging == 0)
+ update_current_battery_picture();
+ }
+
+ sleep_sec(2);
+ set_lcd_backlight(0);
+ lcd_set_power_down(1);
+ mdelay(500); //delay for avoiding lcd blink
+ printf("power off\n");
+ do_wmt_poweroff();
+ }
+
+ if(is_charging == 0)
+ update_current_battery_picture();
+ else
+ display_charge_percent(sp_mem_addr, percent);
+ }
+
+ if(blTimeout_count > max_blTimeout_count) {
+ blTimeout_count = -1;
+ if(pwm_get_enable(g_pwm_setting.pwm_no)) {
+ printf("close backlight during charging\n");
+ set_lcd_backlight(0);
+ }
+ }
+
+ if(readPwrKey_count > max_readPwrKey_count) {
+ readPwrKey_count = 0;
+ if((PMPB_VAL & BIT24) || (PMWS_VAL & BIT14)) {
+ if(PMWS_VAL & BIT14)
+ PMWS_VAL |= BIT14;
+ if(is_powerKey_press == 0) {
+ backup_pwm_status = pwm_get_enable(g_pwm_setting.pwm_no);
+ printf("press pwr key, backup_pwm_status = %d\n", backup_pwm_status);
+ if(!backup_pwm_status) {
+ set_lcd_backlight(1);
+ if(is_charging == 0)
+ update_current_battery_picture();
+ }
+
+ is_powerKey_press = 1;
+ blTimeout_count = -1;
+ longPress_count = 0;
+ }
+ } else {
+ if(is_powerKey_press == 1) {
+ printf("release pwr key, backup_pwm_status = %d\n", backup_pwm_status);
+ is_powerKey_press = 0;
+ if(backup_pwm_status) {
+ if(pwm_get_enable(g_pwm_setting.pwm_no))
+ set_lcd_backlight(0);
+ blTimeout_count = -1;
+ } else {
+ if(!pwm_get_enable(g_pwm_setting.pwm_no)) {
+ set_lcd_backlight(1);
+ if(is_charging == 0)
+ update_current_battery_picture();
+ }
+ blTimeout_count = 0;
+ }
+ }
+ longPress_count = -1;
+ }
+ }
+
+ if(longPress_count > max_longPress_count) {
+ printf("charge_animation: long press key detected\n");
+ // if is_charging = 0 and detect battery low, don't startup system
+ if(is_charging == 0 && wmt_battery_is_lowlevel() > 0) {
+ printf("USB connect to PC and low power. skip long press\n");
+ } else
+ break;
+ }
+
+ udelay(PERIOD_CHECK * 1000);
+
+ //if is_charging = 0, don't play animation
+ if(is_charging == 0)
+ continue;
+
+ if(play_count >= 0)
+ play_count++;
+
+ if(pause_count >= 0)
+ pause_count++;
+
+ if(play_count > max_play_count) {
+ show_charge_picture(sp_mem_addr, frame_index);
+
+ if((frame_index == start_index) || (frame_index == frame_num - 1)) { //a play period complete
+ pause_count = 0; //enable pause
+ play_count = -1; //disable play
+ } else {
+ play_count = 0; //restart play period
+ pause_count = -1;
+ }
+
+ frame_index++;
+ if(frame_index >= frame_num)
+ frame_index = start_index;
+ }
+
+ if(pause_count > max_pause_count) {
+ if((start_index == frame_num - 1) && (frame_index == start_index)) { //the battery is full, always pause, don't play
+ if(battery_is_full == 0) {
+ display_charge_percent(sp_mem_addr, percent);
+ show_charge_picture(sp_mem_addr, frame_index);
+ battery_is_full = 1;
+ }
+ play_count = -1; //disable play
+ pause_count = 0; //enable pause
+ } else {
+ play_count = 0; //enable play
+ pause_count = -1; //disable pause
+ battery_is_full = 0;
+ }
+ }
+ }
+
+ //restore cpu freq
+ set_arm_freq(saved_arm_freq / 1000000);
+ //current_arm_freq = auto_pll_divisor(DEV_ARM, GET_FREQ, 0, 0);
+ //printf("restore cpu freq = %d\n", current_arm_freq);
+
+ return 0;
+}
+
+static int do_check_usbtopc(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int ret;
+ int delay = 0;
+ int max_delay = 300;
+ int exit_flag = 0;
+
+ ret = udc_fastboot_init();
+ if(ret)
+ return -1;
+
+ while (++delay <= max_delay) {
+ udc_fastboot_transfer();
+ if(wmt_udc_connected()) {
+ printf("usb connetct = 1, delay = %d\n", delay);
+ break;
+ }
+ exit_flag |= ctrlc();
+ if(exit_flag)
+ break;
+ mdelay(1);
+ }
+
+ if(delay > max_delay)
+ printf("usb connetct = 0\n");
+
+ udc_fastboot_exit();
+
+ return 0;
+}
+
+
+U_BOOT_CMD(
+ isusbtopc, 1, 0, do_check_usbtopc,
+ "isusbtopc - check if usb connect to pc\n",
+ "- check if usb connect to pc\n"
+);
+
diff --git a/common/wmt_display/cmd_mbit.c b/common/wmt_display/cmd_mbit.c new file mode 100755 index 0000000..89c307d --- /dev/null +++ b/common/wmt_display/cmd_mbit.c @@ -0,0 +1,107 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#include <config.h> +#include <common.h> +#include <command.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> + +#include "wmt_display.h" +#include "com-vpp.h" + +void excute_reg_op(char * p) +{ + ulong addr; + ulong val, org; + char op; + char * endp; + + while(1) + { + addr = simple_strtoul(p, &endp, 16); + if( *endp == '\0') + break; + + op = *endp; + if( endp[1] == '~') + { + val = simple_strtoul(endp+2, &endp, 16); + val = ~val; + } + else + { + val = simple_strtoul(endp+1, &endp, 16); + } + if (addr&0x03) { + printf(" address not alginment to 32bit , address = 0x%x\n",addr); + goto nextcheck; + } + printf(" reg op: 0x%X %c 0x%X\n", addr, op, val); + org = REG32_VAL(addr); + switch(op) + { + case '|': org |= val; break; + case '=': org = val ; break; + case '&': org &= val; break; + default: + printf("Error, Unknown operator %c\n", op); + break; + } + REG32_VAL(addr) = org; +nextcheck: + if(*endp == '\0') + break; + p = endp + 1; + } + return; +} + + +static int wmt_do_mbit (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + default: + if (argc == 2) { + excute_reg_op(argv[1]); + return 0; + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + } + return 0; +} + +U_BOOT_CMD( + mbit, 2, 1, wmt_do_mbit, + "memory bit operation : \n" + "Format : mbit <parameter>\n", + "Puepose : write bit to memory\n" + "Example : mbit -int D8000012|~1\n" + " VAL32(0xD8000012) | 0xFFFFFFFE" + +); diff --git a/common/wmt_display/cmd_textout.c b/common/wmt_display/cmd_textout.c new file mode 100755 index 0000000..dfc4d2d --- /dev/null +++ b/common/wmt_display/cmd_textout.c @@ -0,0 +1,161 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ +#include <common.h> +#include <command.h> +#include <linux/ctype.h> +#include <asm/arch/common_def.h> + +#include "wmt_display.h" +#include "minivgui.h" + +//#define CHAR_WIDTH 8 +//#define CHAR_HEIGHT 20 // 16 + +int text_x = 30, text_y = 30 - CHAR_HEIGHT; +// ------------------- Extern Variable ------------------------ +extern int g_display_direction; + +//-------------------- Extern Function ----------------------- +extern void mv_initPrimary(int no,const mv_surface * s); +//extern void arm_memset(void * s, int c, size_t count); +extern int display_init(int on, int force); + +static int atoi(char *s) //added by howayhuo +{ + int i,n,sign; + + for(i=0;isspace(s[i]);i++) //Ìø¹ý¿Õ°×·û + ; + sign=(s[i]=='-')?-1:1; + if(s[i]=='+'||s[i]=='-') //Ìø¹ý·ûºÅ + i++; + for(n=0;isdigit(s[i]);i++) + n=10*n+(s[i]-'0'); //½«Êý×Ö×Ö·ûת»»³ÉÕûÐÎÊý×Ö + return sign *n; +} + +int do_textout(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int tmpx, tmpy; + unsigned int rgb = 0; + char *text_first, *text_last; + char r, g, b; + int i, len, textLen; + mv_Rect rect; + char tmpbuf[200]; + int no; + mv_surface *s; + + if(display_init(1, 0)) + return -1; + + switch (argc) { + case 1: + case 2: + case 3: /* use load_addr as default address */ + case 4: /* use argument */ + printf("<ERROR> too few argument\n"); + printf ("Usage:\n%s\n", cmdtp->usage); + return -1; + + default: + //tmpx = simple_strtoul(argv[1], NULL, 10); + //tmpy = simple_strtoul(argv[2], NULL, 10); + tmpx = atoi(argv[1]); + tmpy = atoi(argv[2]); + + //printf("tmpx=%d, tmpy=%d\n", tmpx,tmpy); + + if(tmpx >= 0) + text_x = tmpx; + + if(tmpy >= 0) + text_y = tmpy; + else + text_y = text_y + CHAR_HEIGHT; + + printf("x=%d, y=%d\n", text_y, text_y); + + rgb = simple_strtoul(argv[argc - 1], NULL, 16); + + text_first = argv[3]; + if(*text_first != '"') { + printf("<ERROR> please specify the text begin with \" \n", *text_first); + printf ("Usage:\n%s\n", cmdtp->usage); + + return -1; + } + + text_last = argv[argc - 2]; + while(*text_last != '\0') + text_last++; + + if(*--text_last != '"') { + printf("<ERROR> please specify the text end with \" \n", *text_last); + printf ("Usage:\n%s\n", cmdtp->usage); + return -1; + } + break; + } + len = 0; + for(i = 3; i < argc - 1; i++) { + printf("%s ", argv[i]); + len += sprintf(tmpbuf + len, "%s ", argv[i]); + } + printf("\n"); + //if you input: + // drawtext 0 0 "aa bb cc" ff0000 + //then the tmpbuf is ["aa bb cc" ], it have redundant space at the end. + tmpbuf[len - 2] = '\0'; //ignore the last 'double quotation marks' and 'space' + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = mv_getSurface(no); + if(s->startAddr == 0) + continue; + + textLen = len - 3; // total len- ' start " ' (1 char) - 'space' (1 char) -' end " ' (1 char) + rect.left = 0; + rect.top = text_y; + rect.right = s->width; //vfb_var.xres; + rect.bottom = text_y + CHAR_HEIGHT; + if(g_display_direction == 0 || g_display_direction == 2) //the screen is portrait + rect.right = s->height; //vfb_var.yres; + + mv_fillRect(no, &rect, 0, 0, 0); + + r = (rgb >> 16) & 0xFF; + g = (rgb >> 8) & 0xFF; + b = rgb & 0xFF; + mv_textOut(no, text_x, text_y, tmpbuf + 1, r, g, b); + } + + return 0; +} + +U_BOOT_CMD( + textout, 100, 5, do_textout, + "textout - show text to the screen. Example: textout 0 0 \\\"hello world\\\" FFFFFF\n", + "- show text to the screen \n" + "usage: textout x y \"str\" color\n" + "(x,y) is the coordinate. x, y are decimal. (x,y) default value is (30,30)\n" + "if x < 0, the x coordinate is unchaged\n" + "if y < 0, the y coordinate auto add 22 pixels to move to next line\n" + "color is 24bit Hex, R[23:16], G[15:8], B[7:0]\n" + "for example: textout 0 0 \\\"hello world\\\" FFFFFF\n" + " textout -1 -1 \\\"come on\\\" FF0000\n" +); + diff --git a/common/wmt_display/com-fb.h b/common/wmt_display/com-fb.h new file mode 100755 index 0000000..328bdbf --- /dev/null +++ b/common/wmt_display/com-fb.h @@ -0,0 +1,143 @@ +/*++ + * linux/drivers/video/wmt/com-fb.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef COM_FB_H +#define COM_FB_H + +#ifdef __KERNEL__ +#include <linux/fb.h> +#else +#define FB_MODE_IS_VESA 4 +#define FB_MODE_IS_FROM_VAR 32 + +#define FB_SYNC_HOR_HIGH_ACT 1 +#define FB_SYNC_VERT_HIGH_ACT 2 + +#define FB_VMODE_NONINTERLACED 0 /* non interlaced */ +#define FB_VMODE_INTERLACED 1 /* interlaced */ +#define FB_VMODE_DOUBLE 2 /* double scan */ + +struct fb_bitfield { + __u32 offset; /* beginning of bitfield */ + __u32 length; /* length of bitfield */ + __u32 msb_right; /* != 0 : Most significant bit is */ + /* right */ +}; + +struct fb_var_screeninfo { + __u32 xres; /* visible resolution */ + __u32 yres; + __u32 xres_virtual; /* virtual resolution */ + __u32 yres_virtual; + __u32 xoffset; /* offset from virtual to visible */ + __u32 yoffset; /* resolution */ + + __u32 bits_per_pixel; /* guess what */ + __u32 grayscale; /* != 0 Graylevels instead of colors */ + + struct fb_bitfield red; /* bitfield in fb mem if true color, */ + struct fb_bitfield green; /* else only length is significant */ + struct fb_bitfield blue; + struct fb_bitfield transp; /* transparency */ + + __u32 nonstd; /* != 0 Non standard pixel format */ + + __u32 activate; /* see FB_ACTIVATE_* */ + + __u32 height; /* height of picture in mm */ + __u32 width; /* width of picture in mm */ + + __u32 accel_flags; /* (OBSOLETE) see fb_info.flags */ + + /* Timing: All values in pixclocks, except pixclock (of course) */ + __u32 pixclock; /* pixel clock in ps (pico seconds) */ + __u32 left_margin; /* time from sync to picture */ + __u32 right_margin; /* time from picture to sync */ + __u32 upper_margin; /* time from sync to picture */ + __u32 lower_margin; + __u32 hsync_len; /* length of horizontal sync */ + __u32 vsync_len; /* length of vertical sync */ + __u32 sync; /* see FB_SYNC_* */ + __u32 vmode; /* see FB_VMODE_* */ + __u32 rotate; /* angle we rotate counter clockwise */ + __u32 reserved[5]; /* Reserved for future compatibility */ +}; + +struct fb_fix_screeninfo { + char id[16]; /* identification string eg "TT Builtin" */ + unsigned long smem_start; /* Start of frame buffer mem */ + /* (physical address) */ + __u32 smem_len; /* Length of frame buffer mem */ + __u32 type; /* see FB_TYPE_* */ + __u32 type_aux; /* Interleave for interleaved Planes */ + __u32 visual; /* see FB_VISUAL_* */ + __u16 xpanstep; /* zero if no hardware panning */ + __u16 ypanstep; /* zero if no hardware panning */ + __u16 ywrapstep; /* zero if no hardware ywrap */ + __u32 line_length; /* length of a line in bytes */ + unsigned long mmio_start; /* Start of Memory Mapped I/O */ + /* (physical address) */ + __u32 mmio_len; /* Length of Memory Mapped I/O */ + __u32 accel; /* Indicate to driver which */ + /* specific chip/card we have */ + __u16 reserved[3]; /* Reserved for future compatibility */ +}; + +struct fb_info { + int node; + int flags; + struct fb_var_screeninfo var; /* Current var */ + struct fb_fix_screeninfo fix; /* Current fix */ + + __u32 state; /* Hardware state i.e suspend */ + void *fbcon_par; /* fbcon use-only private area */ + /* From here on everything is device dependent */ + void *par; +}; + +struct fb_videomode { + const char *name; /* optional */ + unsigned int refresh; + unsigned int xres; + unsigned int yres; + unsigned int pixclock; + unsigned int left_margin; + unsigned int right_margin; + unsigned int upper_margin; + unsigned int lower_margin; + unsigned int hsync_len; + unsigned int vsync_len; + unsigned int sync; + unsigned int vmode; + unsigned int flag; +}; + +#define KHZ2PICOS(a) (1000000000UL/(a)) +#define PICOS2KHZ(a) (1000000000UL/(a)) + +struct timeval { + int tv_sec; + int tv_usec; +}; +#endif // __KERNEL__ +#endif // COM_FB_H diff --git a/common/wmt_display/com-video.h b/common/wmt_display/com-video.h new file mode 100755 index 0000000..80cf508 --- /dev/null +++ b/common/wmt_display/com-video.h @@ -0,0 +1,103 @@ +/*++ +Copyright (c) 2008 WonderMedia Technologies, Inc. All Rights Reserved. + +This PROPRIETARY SOFTWARE is the property of WonderMedia Technologies, Inc. +and may contain trade secrets and/or other confidential information of +WonderMedia Technologies, Inc. This file shall not be disclosed to any third +party, in whole or in part, without prior written consent of WonderMedia. + +THIS PROPRIETARY SOFTWARE AND ANY RELATED DOCUMENTATION ARE PROVIDED AS IS, +WITH ALL FAULTS, AND WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS OR IMPLIED, +AND WonderMedia TECHNOLOGIES, INC. DISCLAIMS ALL EXPRESS OR IMPLIED WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR +NON-INFRINGEMENT. +--*/ + +#ifndef COM_VIDEO_H +/* To assert that only one occurrence is included */ +#define COM_VIDEO_H + +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ + +//#include "sim-kernel.h" // for POST only + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ + +#define BIT(x) (1<<x) + + +/*------------------------------------------------------------------------------ + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + Definitions of enum +------------------------------------------------------------------------------*/ + +typedef enum { + VDO_COL_FMT_YUV420, + VDO_COL_FMT_YUV422H, + VDO_COL_FMT_YUV422V, + VDO_COL_FMT_YUV444, + VDO_COL_FMT_YUV411, + VDO_COL_FMT_GRAY, + VDO_COL_FMT_BGRA, /* B G R A from offset 0 ~ 3 */ + VDO_COL_FMT_ARGB = VDO_COL_FMT_BGRA, + VDO_COL_FMT_AUTO, + VDO_COL_FMT_RGB_888, + VDO_COL_FMT_RGB_666, + VDO_COL_FMT_RGB_565, + VDO_COL_FMT_RGB_1555, + VDO_COL_FMT_RGB_5551, + VDO_COL_FMT_RGBA, /* R G B A from offset 0 ~ 3 */ + VDO_COL_FMT_ABGR = VDO_COL_FMT_RGBA, + VDO_COL_FMT_MAX, + VDO_COL_FMT_UNKNOWN +} vdo_color_fmt; + + +/*------------------------------------------------------------------------------ + Definitions of Struct +------------------------------------------------------------------------------*/ + +typedef struct { + /* Physical address for kernel space */ + unsigned int y_addr; /* Addr of Y plane in YUV domain or RGB plane in ARGB domain */ + unsigned int c_addr; /* C plane address */ + unsigned int y_size; /* Buffer size in bytes */ + unsigned int c_size; /* Buffer size in bytes */ + unsigned int img_w; /* width of valid image (unit: pixel) */ + unsigned int img_h; /* height of valid image (unit: line) */ + unsigned int fb_w; /* width of frame buffer (scanline offset) (unit: pixel)*/ + unsigned int fb_h; /* height of frame buffer (unit: line) */ + unsigned int bpp; /* bits per pixel (8/16/24/32) */ + + vdo_color_fmt col_fmt; /* Color format on frame buffer */ + + unsigned int h_crop; /* Horental Crop (unit: pixel) */ + unsigned int v_crop; /* Vertical Crop (unit: pixel) */ + + unsigned int flag; /* frame flags */ +} vdo_framebuf_t; + +#define VDO_FLAG_INTERLACE BIT(0) +#define VDO_FLAG_MOTION_VECTOR BIT(1) /* frame buffer with motion vector table after C frame */ +#define VDO_FLAG_MB_ONE BIT(2) /* Y/C frame alloc in one mb */ +#define VDO_FLAG_MB_NO BIT(3) /* frame buffer is not alloc from mb */ + +typedef struct { + unsigned int resx_src; /* source x resolution */ + unsigned int resy_src; /* source y resolution */ + unsigned int resx_virtual; /* virtual x resolution */ + unsigned int resy_virtual; /* virtual y resolution */ + unsigned int resx_visual; /* visual x resolution */ + unsigned int resy_visual; /* visual y resolution */ + unsigned int posx; /* x position to display screen */ + unsigned int posy; /* y postion to display screen */ + unsigned int offsetx; /* x pixel offset from source left edge */ + unsigned int offsety; /* y pixel offset from source top edge */ +} vdo_view_t; + +#endif /* ifndef COM_VIDEO_H */ + +/*=== END com-video.h ==========================================================*/ diff --git a/common/wmt_display/com-vpp.h b/common/wmt_display/com-vpp.h new file mode 100755 index 0000000..ce6f2c3 --- /dev/null +++ b/common/wmt_display/com-vpp.h @@ -0,0 +1,455 @@ +/*++ + * linux/drivers/video/wmt/com-vpp.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef COM_VPP_H +#define COM_VPP_H + +#ifdef __KERNEL__ + #include <linux/types.h> + #include <linux/fb.h> + #include <asm/io.h> + #include <mach/common_def.h> + #include <mach/com-video.h> +#else + #include "com-video.h" +#ifdef CFG_LOADER + #include "com-fb.h" +#endif +#endif + +#define VPP_NEW_FBUF_MANAGER + +#define VPP_AHB_CLK 250000000 + +#ifdef CONFIG_MAX_RESX + #define VPP_HD_MAX_RESX CONFIG_MAX_RESX +#else + #define VPP_HD_MAX_RESX 1920 +#endif + +#ifdef CONFIG_MAX_RESY + #define VPP_HD_MAX_RESY CONFIG_MAX_RESY +#else + #define VPP_HD_MAX_RESY 1200 +#endif + +#ifdef CONFIG_DEFAULT_RESX + #define VPP_HD_DISP_RESX CONFIG_DEFAULT_RESX +#else + #define VPP_HD_DISP_RESX 1024 +#endif + +#ifdef CONFIG_DEFAULT_RESY + #define VPP_HD_DISP_RESY CONFIG_DEFAULT_RESY +#else + #define VPP_HD_DISP_RESY 768 +#endif + +#ifdef CONFIG_DEFAULT_FPS + #define VPP_HD_DISP_FPS CONFIG_DEFAULT_FPS +#else + #define VPP_HD_DISP_FPS 60 +#endif + +#define VPP_HD_DISP_PIXCLK 65000000 + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 + +#define VPP_YUV_BLACK 0x008080 /* Y, Cr, Cb */ +#define VPP_YUV_WHITE 0xff8080 +#define VPP_YUV_RED 0x51f05a +#define VPP_YUV_GREEN 0x902235 +#define VPP_YUV_BLUE 0x286df0 +#define VPP_RGB32_BLACK 0x00000000 + +#define VPP_COL_RGB32_BLACK 0x000000 +#define VPP_COL_RGB32_WHITE 0xFFFFFF +#define VPP_COL_RGB32_RED 0xFF0000 +#define VPP_COL_RGB32_GREEN 0x00FF00 +#define VPP_COL_RGB32_BLUE 0x0000FF + +#define VPP_COL_BLACK 0x008080 /* Y, Cr, Cb */ +#define VPP_COL_WHITE 0xff8080 +#define VPP_COL_RED 0x41d464 +#define VPP_COL_GREEN 0x902235 +#define VPP_COL_BLUE 0x2372d4 + +#define VPP_MAGNUM(s, e) ((2^((s)-(e)+1))-1) + +#define WMT_FB_COLFMT(a) (a & 0xFF) + +enum vpp_fbuf_s { + VPP_FBUF_GOVR_1, + VPP_FBUF_GOVR_2, + VPP_FBUF_SCLR_1, + VPP_FBUF_SCLR_2, + VPP_FBUF_MAX +}; +#define vpp_fbuf_t enum vpp_fbuf_s + +enum vpp_flag_s { + VPP_FLAG_NULL = 0, + VPP_FLAG_ENABLE = 1, + VPP_FLAG_DISABLE = 0, + VPP_FLAG_TRUE = 1, + VPP_FLAG_FALSE = 0, + VPP_FLAG_ZERO = 0, + VPP_FLAG_ONE = 1, + VPP_FLAG_SUCCESS = 1, + VPP_FLAG_ERROR = 0, + VPP_FLAG_RD = 1, + VPP_FLAG_WR = 0, +}; +#define vpp_flag_t enum vpp_flag_s + +enum vpp_mod_s { + VPP_MOD_GOVRH2, + VPP_MOD_GOVRH, + VPP_MOD_DISP, + VPP_MOD_GOVW, + VPP_MOD_GOVM, + VPP_MOD_SCL, + VPP_MOD_SCLW, + VPP_MOD_VPU, + VPP_MOD_VPUW, + VPP_MOD_PIP, + VPP_MOD_VPPM, + VPP_MOD_LCDC, + VPP_MOD_CURSOR, + VPP_MOD_MAX +}; +#define vpp_mod_t enum vpp_mod_s + +enum vpp_vout_s { + VPP_VOUT_NONE = 0, + VPP_VOUT_SDA = 1, + VPP_VOUT_LCD = 2, + VPP_VOUT_DVI = 3, + VPP_VOUT_HDMI = 4, + VPP_VOUT_DVO2HDMI = 5, + VPP_VOUT_LVDS = 6, + VPP_VOUT_VGA = 7, + VPP_VOUT_FBDEV = 8, + VPP_VOUT_VIRDISP = 9, + VPP_VOUT_MAX +}; +#define vpp_vout_t enum vpp_vout_s + +enum vpp_display_format_s { + VPP_DISP_FMT_FRAME, /* Progressive */ + VPP_DISP_FMT_FIELD, /* Interlace */ + VPP_DISP_FMT_MAX, +}; +#define vpp_display_format_t enum vpp_display_format_s + +enum vpp_media_format_s { + VPP_MEDIA_FMT_MPEG, + VPP_MEDIA_FMT_H264, + VPP_MEDIA_FMT_MAX, +}; +#define vpp_media_format_t enum vpp_media_format_s + +enum vpp_csc_s { /* don't change this order */ + VPP_CSC_YUV2RGB2_MIN, + VPP_CSC_YUV2RGB_SDTV_0_255 = VPP_CSC_YUV2RGB2_MIN, + VPP_CSC_YUV2RGB_SDTV_16_235, + VPP_CSC_YUV2RGB_HDTV_0_255, + VPP_CSC_YUV2RGB_HDTV_16_235, + VPP_CSC_YUV2RGB_JFIF_0_255, + VPP_CSC_YUV2RGB_SMPTE170M, + VPP_CSC_YUV2RGB_SMPTE240M, + VPP_CSC_RGB2YUV_MIN, + VPP_CSC_RGB2YUV_SDTV_0_255 = VPP_CSC_RGB2YUV_MIN, + VPP_CSC_RGB2YUV_SDTV_16_235, + VPP_CSC_RGB2YUV_HDTV_0_255, + VPP_CSC_RGB2YUV_HDTV_16_235, + VPP_CSC_RGB2YUV_JFIF_0_255, + VPP_CSC_RGB2YUV_SMPTE170M, + VPP_CSC_RGB2YUV_SMPTE240M, + VPP_CSC_RGB2YUV_JFIF_VT1625, + VPP_CSC_MAX, + VPP_CSC_BYPASS +}; +#define vpp_csc_t enum vpp_csc_s + +enum vpp_reglevel_s { + VPP_REG_LEVEL_1, + VPP_REG_LEVEL_2, + VPP_REG_LEVEL_MAX, +}; +#define vpp_reglevel_t enum vpp_reglevel_s + +enum vpp_datawidht_s { + VPP_DATAWIDHT_12, + VPP_DATAWIDHT_24, + VPP_DATAWIDHT_MAX, +}; +#define vpp_datawidht_t enum vpp_datawidht_s + +enum vpp_tvsys_s { + VPP_TVSYS_NTSC, + VPP_TVSYS_NTSCJ, + VPP_TVSYS_NTSC443, + VPP_TVSYS_PAL, + VPP_TVSYS_PALM, + VPP_TVSYS_PAL60, + VPP_TVSYS_PALN, + VPP_TVSYS_PALNC, + VPP_TVSYS_720P, + VPP_TVSYS_1080I, + VPP_TVSYS_1080P, + VPP_TVSYS_MAX +}; +#define vpp_tvsys_t enum vpp_tvsys_s + +enum vpp_tvconn_s { + VPP_TVCONN_YCBCR, + VPP_TVCONN_SCART, + VPP_TVCONN_YPBPR, + VPP_TVCONN_VGA, + VPP_TVCONN_SVIDEO, + VPP_TVCONN_CVBS, + VPP_TVCONN_MAX +}; +#define vpp_tvconn_t enum vpp_tvconn_s + +#define VPP_OPT_INTERLACE 0x01 +#define VPP_DVO_SYNC_POLAR_HI 0x08 +#define VPP_DVO_VSYNC_POLAR_HI 0x10 + +struct vpp_clock_s { + int read_cycle; + + unsigned int total_pixel_of_line; + unsigned int begin_pixel_of_active; + unsigned int end_pixel_of_active; + + unsigned int total_line_of_frame; + unsigned int begin_line_of_active; + unsigned int end_line_of_active; + + unsigned int hsync; + unsigned int vsync; + unsigned int line_number_between_VBIS_VBIE; + unsigned int line_number_between_PVBI_VBIS; +}; +#define vpp_clock_t struct vpp_clock_s + +struct vpp_scale_s { + vdo_framebuf_t src_fb; + vdo_framebuf_t dst_fb; +}; +#define vpp_scale_t struct vpp_scale_s + +struct vpp_scale_overlap_s { + int mode; + vdo_framebuf_t src_fb; + vdo_framebuf_t src2_fb; + vdo_framebuf_t dst_fb; +}; +#define vpp_scale_overlap_t struct vpp_scale_overlap_s + +struct vpp_overlap_s { + unsigned int alpha_src_type:2; /* 0-mif1,1-mif2,2-fix */ + unsigned int alpha_src:8; + unsigned int alpha_dst_type:2; /* 0-mif1,1-mif2,2-fix */ + unsigned int alpha_dst:8; + unsigned int alpha_swap:1; /* 0-(alpha,1-alpha),1:(1-alpha,alpha) */ + unsigned int color_key_from:2; /* 0-RMIF1,1-RMIF2 */ + unsigned int color_key_comp:2; /* 0-888,1-777,2-666,3-555 */ + unsigned int color_key_mode:3; /* (Non-Hit,Hit):0/1-(alpha,alpha), + 2-(alpha,pix1), 3-(pix1,alpha),4-(alpha,pix2), + 5-(pix2,alpha),6-(pix1,pix2),7-(pix2,pix1) */ + unsigned int reserved:4; + unsigned int color_key; /* ARGB */ +}; +#define vpp_overlap_t struct vpp_overlap_s + +#define VPP_VOUT_STS_REGISTER 0x01 +#define VPP_VOUT_STS_ACTIVE 0x02 +#define VPP_VOUT_STS_PLUGIN 0x04 +#define VPP_VOUT_STS_EDID 0x08 +#define VPP_VOUT_STS_BLANK 0x10 +#define VPP_VOUT_STS_POWERDN 0x20 +#define VPP_VOUT_STS_CONTENT_PROTECT 0x40 +#define VPP_VOUT_STS_FB 0xF00 +#define VPP_VOUT_ARG_NUM 5 +struct vpp_vout_info_s { + enum vpp_vout_s mode[VPP_VOUT_ARG_NUM]; + unsigned int status[VPP_VOUT_ARG_NUM]; +}; +#define vpp_vout_info_t struct vpp_vout_info_s + +struct vpp_vout_parm_s { + int num; + int arg; +}; +#define vpp_vout_parm_t struct vpp_vout_parm_s + +#define VOUT_OPT_BLANK BIT(8) + +#define VPP_CAP_DUAL_DISPLAY BIT(0) +struct vpp_cap_s { + unsigned int chip_id; + unsigned int version; + unsigned int resx_max; + unsigned int resy_max; + unsigned int pixel_clk; + unsigned int module; + unsigned int option; +}; +#define vpp_cap_t struct vpp_cap_s + +struct vpp_i2c_s { + unsigned int addr; + unsigned int index; + unsigned int val; +}; +#define vpp_i2c_t struct vpp_i2c_s + +struct vpp_mod_fbinfo_s { + vpp_mod_t mod; + int read; + vdo_framebuf_t fb; +}; +#define vpp_mod_fbinfo_t struct vpp_mod_fbinfo_s + +struct vpp_vmode_parm_s { + unsigned int resx; + unsigned int resy; + unsigned int fps; + unsigned int option; +}; +#define vpp_vmode_parm_t struct vpp_vmode_parm_s + +#define VPP_VOUT_VMODE_NUM 20 +struct vpp_vout_vmode_s { + vpp_vout_t mode; + int num; + vpp_vmode_parm_t parm[VPP_VOUT_VMODE_NUM]; +}; +#define vpp_vout_vmode_t struct vpp_vout_vmode_s + +struct vpp_vout_edid_s { + vpp_vout_t mode; + int size; + char *buf; +}; +#define vpp_vout_edid_t struct vpp_vout_edid_s + +struct vpp_vout_cp_info_s { + int num; + unsigned int bksv[2]; +}; +#define vpp_vout_cp_info_t struct vpp_vout_cp_info_s + +#define VPP_VOUT_CP_NUM 336 +struct vpp_vout_cp_key_s { + char key[VPP_VOUT_CP_NUM]; +}; +#define vpp_vout_cp_key_t struct vpp_vout_cp_key_s + +struct vpp_mod_parm_t { + vpp_mod_t mod; + int read; + unsigned int parm; +}; + +#define VPPIO_MAGIC 'f' + +/* VPP common ioctl command */ +#define VPPIO_VPP_BASE 0x0 +#define VPPIO_VPPGET_INFO _IOR(VPPIO_MAGIC, VPPIO_VPP_BASE + 0, vpp_cap_t) +#define VPPIO_VPPSET_INFO _IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 0, vpp_cap_t) +#define VPPIO_I2CSET_BYTE _IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 1, vpp_i2c_t) +#define VPPIO_I2CGET_BYTE _IOR(VPPIO_MAGIC, VPPIO_VPP_BASE + 1, vpp_i2c_t) +#define VPPIO_MODSET_CSC \ + _IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 2, struct vpp_mod_parm_t) +#define VPPIO_MODULE_FBINFO \ + _IOWR(VPPIO_MAGIC, VPPIO_VPP_BASE + 6, vpp_mod_fbinfo_t) +#define VPPIO_STREAM_ENABLE _IO(VPPIO_MAGIC, VPPIO_VPP_BASE + 12) +#define VPPIO_STREAM_GETFB \ + _IOR(VPPIO_MAGIC, VPPIO_VPP_BASE + 13, vdo_framebuf_t) +#define VPPIO_STREAM_PUTFB \ + _IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 13, vdo_framebuf_t) +#define VPPIO_MULTIVD_ENABLE _IO(VPPIO_MAGIC, VPPIO_VPP_BASE + 15) + +/* VOUT ioctl command */ +#define VPPIO_VOUT_BASE 0x10 +#define VPPIO_VOGET_INFO _IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 0, vpp_vout_info_t) +#define VPPIO_VOGET_HDMI_3D \ + _IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 1, struct vpp_vout_parm_s) +#define VPPIO_VOUT_VMODE \ + _IOWR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 7, vpp_vout_vmode_t) +#define VPPIO_VOGET_EDID _IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 8, vpp_vout_edid_t) +#define VPPIO_VOGET_CP_INFO \ + _IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 9, vpp_vout_cp_info_t) +#define VPPIO_VOSET_CP_KEY \ + _IOW(VPPIO_MAGIC, VPPIO_VOUT_BASE + 10, vpp_vout_cp_key_t) +#define VPPIO_VOSET_AUDIO_PASSTHRU _IO(VPPIO_MAGIC, VPPIO_VOUT_BASE + 11) +#define VPPIO_VOSET_VIRTUAL_FBDEV _IO(VPPIO_MAGIC, VPPIO_VOUT_BASE + 13) + +/* SCL ioctl command */ +#define VPPIO_SCL_BASE 0x60 +#define VPPIO_SCL_SCALE _IOWR(VPPIO_MAGIC, VPPIO_SCL_BASE + 0, vpp_scale_t) +#define VPPIO_SCL_SCALE_ASYNC \ + _IOWR(VPPIO_MAGIC, VPPIO_SCL_BASE + 2, vpp_scale_t) +#define VPPIO_SCL_SCALE_FINISH _IO(VPPIO_MAGIC, VPPIO_SCL_BASE + 3) +#define VPPIO_SCLSET_OVERLAP \ + _IOW(VPPIO_MAGIC, VPPIO_SCL_BASE + 4, vpp_overlap_t) +#define VPPIO_SCL_SCALE_OVERLAP \ + _IOWR(VPPIO_MAGIC, VPPIO_SCL_BASE + 5, vpp_scale_overlap_t) + +#define VPPIO_MAX 0x70 +#endif /* COM_VPP_H */ diff --git a/common/wmt_display/devices/cs8556.c b/common/wmt_display/devices/cs8556.c new file mode 100755 index 0000000..81a6455 --- /dev/null +++ b/common/wmt_display/devices/cs8556.c @@ -0,0 +1,400 @@ +/*++
+ * linux/drivers/video/wmt/cs8556.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013 WonderMedia Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define CS8556_C
+// #define DEBUG
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../vout.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define VT1632_XXXX xxxx *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define VT1632_XXXX 1 *//*Example*/
+#define CS8556_ADDR 0x3d
+#define CS8556_NAME "CS8556"
+
+/*----------------------- PRIVATE TYPE --------------------------------------*/
+/* typedef xxxx vt1632_xxx_t; *//*Example*/
+typedef enum {
+ TV_PAL,
+ TV_NTSC,
+ TV_UNDEFINED,
+ TV_MAX
+} vout_tvformat_t;
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in vt1632.h -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int vt1632_xxx; *//*Example*/
+static int s_cs8556_ready;
+static int s_cs8556_init;
+static int i2c_no = 1;
+static vout_tvformat_t s_tvformat = TV_MAX;
+
+static unsigned char s_CS8556_Original_Offset0[]={
+ 0xF0,0x7F,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x02,0x01,0x00,0x00,0x01,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static unsigned char s_RGB888_To_PAL_Offset0[]={
+ 0x01,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x5F,0x03,0x3F,0x00,0x7D,0x00,0x53,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x70,0x02,0x04,0x00,0x2E,0x00,0x62,0x02,0x00,0x00,0x84,0x00,0x2B,0x00,0x36,0x00,
+ 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xBF,0x06,0x7F,0x00,0xFE,0x00,0xA4,0x06,0x00,0x00,0x2D,0x11,0x3C,0x01,0x3A,0x01,
+ 0x70,0x02,0x04,0x00,0x12,0x00,0x34,0x01,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,
+ 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x41,0x18,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,
+ 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
+ 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x24,0x1A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x01,0xA4,0x06,0x0B,0x00,0x07,0x01,0xF0,0x00,0x00,0x00,0x00,0x04,0x40,0x01
+};
+
+static unsigned char s_RGB888_To_NTSC_Offset0[]={
+ 0x01,0x80,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x00,0x00,0x00,0x00,
+ 0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x59,0x03,0x3D,0x00,0x7E,0x00,0x49,0x03,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,
+ 0x0C,0x02,0x05,0x00,0x21,0x00,0x03,0x02,0x00,0x00,0x7A,0x00,0x23,0x00,0x16,0x00,
+ 0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xB3,0x06,0x7F,0x00,0x00,0x01,0xA4,0x06,0x00,0x00,0x05,0x50,0x00,0x01,0x07,0x01,
+ 0x0C,0x02,0x02,0x00,0x12,0x00,0x07,0x01,0x00,0x00,0x70,0x70,0x70,0x00,0x00,0x00,
+ 0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x41,0x18,0x09,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x80,0x80,0x00,0x00,0x80,0x80,0x00,0x00,
+ 0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
+ 0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x24,0x1A,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x04,0x01,0xA4,0x06,0x0B,0x00,0x07,0x01,0xF0,0x00,0x00,0x00,0x00,0x04,0x00,0x00
+};
+
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void vt1632_xxx(void); *//*Example*/
+static int I2CMultiPageRead(uchar maddr, uchar page, uchar saddr, int number, uchar *value)
+{
+ int ret;
+ uchar wbuf[2];
+ struct i2c_msg_s rd[2];
+
+ wbuf[0] = page;
+ wbuf[1] = saddr;
+
+ rd[0].addr = maddr;
+ rd[0].flags = I2C_M_WR;
+ rd[0].len = 2;
+ rd[0].buf = wbuf;
+
+ rd[1].addr = maddr;
+ rd[1].flags = I2C_M_RD;
+ rd[1].len = number;
+ rd[1].buf = value;
+
+ switch(i2c_no) {
+ case 0:
+ ret = i2c_transfer(rd, 2);
+ break;
+ case 1:
+ ret = i2c1_transfer(rd, 2);
+ break;
+ case 2:
+ ret = i2c2_transfer(rd, 2);
+ break;
+ case 3:
+ ret = i2c3_transfer(rd, 2);
+ break;
+ default:
+ DBG_ERR("i2c%d isn't exist in wm8880\n", i2c_no);
+ return -1;
+
+ }
+
+ if (ret != 2) {
+ DBG_ERR("fail\n", i2c_no);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int I2CMultiPageWrite(uchar maddr,uchar page,uchar saddr,int number,uchar *value)
+{
+ int ret;
+ uchar *pbuf;
+ struct i2c_msg_s wr[1];
+
+ pbuf = calloc(number + 2, sizeof(uchar));
+
+ pbuf[0] = page;
+ pbuf[1] = saddr;
+
+ memcpy(pbuf + 2, value, number);
+
+ wr[0].addr = maddr;
+ wr[0].flags = I2C_M_WR;
+ wr[0].len = number + 2;
+ wr[0].buf = pbuf;
+
+ switch(i2c_no) {
+ case 0:
+ ret = i2c_transfer(wr, 1);
+ break;
+ case 1:
+ ret = i2c1_transfer(wr, 1);
+ break;
+ case 2:
+ ret = i2c2_transfer(wr, 1);
+ break;
+ case 3:
+ ret = i2c3_transfer(wr, 1);
+ break;
+ default:
+ DBG_ERR("i2c%d isn't exist in wm8880\n", i2c_no);
+ return -1;
+
+ }
+
+ if (ret != 1) {
+ DBG_ERR("fail\n", i2c_no);
+ free(pbuf);
+ return -1;
+ }
+
+ free(pbuf);
+ return 0 ;
+}
+
+/*----------------------- Function Body --------------------------------------*/
+
+static int cs8556_check_plugin(int hotplug)
+{
+ return 1;
+}
+
+static int cs8556_init(struct vout_s *vo)
+{
+ int ret;
+ char buf[40];
+ int varlen = 40;
+ unsigned char rbuf[256] = {0};
+
+ if(s_tvformat == TV_MAX) {
+ if(wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) {
+ if(!strnicmp(buf, "PAL", 3))
+ s_tvformat = TV_PAL;
+ else if(!strnicmp(buf, "NTSC", 4))
+ s_tvformat = TV_NTSC;
+ else
+ s_tvformat = TV_UNDEFINED;
+ }
+ else
+ s_tvformat = TV_UNDEFINED;
+ }
+
+ if(s_tvformat == TV_UNDEFINED)
+ return -1;
+
+ if(!s_cs8556_init) {
+ if(wmt_getsyspara("wmt.cs8556.i2c", buf, &varlen) == 0) {
+ if(strlen(buf) > 0)
+ i2c_no = buf[0] - '0';
+ }
+
+ switch (i2c_no) {
+ case 0:
+ i2c_init(I2C_FAST_MODE, 0);
+ break;
+ case 1:
+ i2c1_init(I2C_FAST_MODE, 0);
+ break;
+ case 2:
+ i2c2_init(I2C_FAST_MODE, 0);
+ break;
+ case 3:
+ i2c3_init(I2C_FAST_MODE, 0);
+ break;
+ default:
+ DBG_ERR("i2c%d isn't exist in wm8850\n", i2c_no);
+ return -1;
+ }
+
+ s_cs8556_init = 1;
+ }
+
+ ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+ if(ret) {
+ DBG_ERR("I2C address 0x%02X is not found\n", CS8556_ADDR);
+ return -1;
+ }
+
+ switch(s_tvformat) {
+ case TV_PAL:
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_PAL_Offset0);
+ if(ret) {
+ DBG_ERR("PAL init fail\n");
+ return -1;
+ }
+ break;
+
+ case TV_NTSC:
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_NTSC_Offset0);
+ if(ret) {
+ DBG_ERR("NTSC init fail\n");
+ return -1;
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ s_cs8556_ready = 1;
+
+ DPRINT("cs8556 init ok\n");
+
+ return 0;
+}
+
+int cs8556_set_mode(unsigned int *option)
+{
+ if(!s_cs8556_ready )
+ return -1;
+
+ return 0;
+}
+
+void cs8556_set_power_down(int enable)
+{
+ int ret;
+ unsigned char rbuf[256] = {0};
+
+ if( !s_cs8556_ready )
+ return;
+
+ //DPRINT("cs8556_set_power_down(%d)\n",enable);
+
+ if(enable == 0) {
+ if(hdmi_get_plugin()) {
+ DPRINT("[CVBS] HDMI plugin. CVBS power down\n");
+ enable = 1;
+ } else
+ DPRINT("[CVBS] HDMI plugout. CVBS power up\n");
+ } else
+ DPRINT("[CVBS] CVBS power down\n");
+
+ ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+ if(ret) {
+ DBG_ERR("I2C read Offset0 fail\n");
+ return;
+ }
+
+ if( enable ){
+ if(memcmp(rbuf, s_CS8556_Original_Offset0, 5) != 0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 5, s_CS8556_Original_Offset0);
+ if(ret)
+ DBG_ERR("I2C write Original_Offset0 fail\n");
+ }
+ }
+ else {
+ switch(s_tvformat) {
+ case TV_PAL:
+ if(memcmp(rbuf, s_RGB888_To_PAL_Offset0, 0x50) != 0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_PAL_Offset0);
+ if(ret)
+ DBG_ERR("I2C write PAL_Offset0 fail\n");
+ }
+ break;
+ case TV_NTSC:
+ if(memcmp(rbuf, s_RGB888_To_NTSC_Offset0, 0x50) !=0) {
+ ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256, s_RGB888_To_NTSC_Offset0);
+ if(ret)
+ DBG_ERR("I2C write NTSC_Offset0 fail\n");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static int cs8556_config(vout_info_t *info)
+{
+ return 0;
+}
+
+static int cs8556_get_edid(char *buf)
+{
+ return -1;
+}
+
+/*
+static int cs8556_interrupt(void)
+{
+ return cs8556_check_plugin(1);
+}
+*/
+/*----------------------- vout device plugin --------------------------------------*/
+vout_dev_t cs8556_vout_dev_ops = {
+ .name = CS8556_NAME,
+ .mode = VOUT_INF_DVI,
+
+ .init = cs8556_init,
+ .set_power_down = cs8556_set_power_down,
+ .set_mode = cs8556_set_mode,
+ .config = cs8556_config,
+ .check_plugin = cs8556_check_plugin,
+ .get_edid = cs8556_get_edid,
+ //.interrupt = cs8556_interrupt,
+};
+
+int cs8556_module_init(void)
+{
+ vout_device_register(&cs8556_vout_dev_ops);
+ return 0;
+} /* End of cs8556_module_init */
+module_init(cs8556_module_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef CS8556_C
+
diff --git a/common/wmt_display/devices/lcd-AUO-A080SN01.c b/common/wmt_display/devices/lcd-AUO-A080SN01.c new file mode 100755 index 0000000..f4602a1 --- /dev/null +++ b/common/wmt_display/devices/lcd-AUO-A080SN01.c @@ -0,0 +1,95 @@ +/*++ + * linux/drivers/video/wmt/lcd-AUO-A080SN01.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_AUO_A080SN01_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_A080SN01_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_A080SN01_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +static void lcd_a080sn01_initial(void); + +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_parm_t lcd_a080sn01_parm = { + .bits_per_pixel = 24, + .capability = 0, + .vmode = { + .name = "AUO A080SN01", + .refresh = 60, + .xres = 800, + .yres = 600, + .pixclock = KHZ2PICOS(40000), + .left_margin = 88, + .right_margin = 40, + .upper_margin = 24, + .lower_margin = 1, + .hsync_len = 128, + .vsync_len = 3, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 162, + .height = 121, + .initial = lcd_a080sn01_initial, +}; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +static void lcd_a080sn01_initial(void) +{ + DPRINT("lcd_a080sn01_initial\n"); + + /* TODO */ +} + +struct lcd_parm_t *lcd_a080sn01_get_parm(int arg) +{ + return &lcd_a080sn01_parm; +} + +int lcd_a080sn01_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_AUO_A080SN01, + (void *) lcd_a080sn01_get_parm); + return ret; +} /* End of lcd_a080sn01_init */ +module_init(lcd_a080sn01_init); + +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_AUO_A080SN01_C + diff --git a/common/wmt_display/devices/lcd-CHILIN-LW700at9003.c b/common/wmt_display/devices/lcd-CHILIN-LW700at9003.c new file mode 100755 index 0000000..af9752b --- /dev/null +++ b/common/wmt_display/devices/lcd-CHILIN-LW700at9003.c @@ -0,0 +1,104 @@ +/*++ + * linux/drivers/video/wmt/lcd-CHILIN-LW700at9003.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_CHILIN_LW700AT9003_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_LW700AT9003_XXXX xxxx *//*Example*/ + + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_LW700AT9003_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +static void lcd_lw700at9003_power_on(void); +static void lcd_lw700at9003_power_off(void); + +/*----------------------- INTERNAL PRIVATE VARIABLES ------------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_parm_t lcd_lw700at9003_parm = { + .bits_per_pixel = 18, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "CHILIN LW700AT9003", + .refresh = 48, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(33260), + .left_margin = 105, + .right_margin = 105, + .upper_margin = 23, + .lower_margin = 22, + .hsync_len = 40, + .vsync_len = 5, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 152, + .height = 91, + .initial = lcd_lw700at9003_power_on, + .uninitial = lcd_lw700at9003_power_off, +}; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +static void lcd_lw700at9003_power_on(void) +{ + DPRINT("lcd_lw700at9003_power_on\n"); + /* TODO */ +} + +static void lcd_lw700at9003_power_off(void) +{ + DPRINT("lcd_lw700at9003_power_off\n"); + + /* TODO */ +} + +struct lcd_parm_t *lcd_lw700at9003_get_parm(int arg) +{ + lcd_lw700at9003_parm.bits_per_pixel = arg; + return &lcd_lw700at9003_parm; +} + +int lcd_lw700at9003_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_CHILIN_LW0700AT9003, + (void *) lcd_lw700at9003_get_parm); + return ret; +} /* End of lcd_oem_init */ +module_init(lcd_lw700at9003_init); + +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_CHILIN_LW700AT9003_C diff --git a/common/wmt_display/devices/lcd-EKING-EK08009-70135.c b/common/wmt_display/devices/lcd-EKING-EK08009-70135.c new file mode 100755 index 0000000..1d40188 --- /dev/null +++ b/common/wmt_display/devices/lcd-EKING-EK08009-70135.c @@ -0,0 +1,103 @@ +/*++ + * linux/drivers/video/wmt/lcd-EKING_EK08009-70135.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_EKING_EK08009_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_EK08009_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_EK08009_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +static void lcd_ek08009_power_on(void); +static void lcd_ek08009_power_off(void); + +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_parm_t lcd_ek08009_parm = { + .bits_per_pixel = 18, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "EKING EK08009", + .refresh = 60, + .xres = 800, + .yres = 600, + .pixclock = KHZ2PICOS(40000), + .left_margin = 46, + .right_margin = 210, + .upper_margin = 24, + .lower_margin = 12, + .hsync_len = 1, + .vsync_len = 1, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 162, + .height = 162, + .initial = lcd_ek08009_power_on, + .uninitial = lcd_ek08009_power_off, +}; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +static void lcd_ek08009_power_on(void) +{ + DPRINT("lcd_ek08009_power_on\n"); + + /* TODO */ +} + +static void lcd_ek08009_power_off(void) +{ + DPRINT("lcd_ek08009_power_off\n"); + + /* TODO */ +} + +struct lcd_parm_t *lcd_ek08009_get_parm(int arg) +{ + return &lcd_ek08009_parm; +} + +int lcd_ek08009_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_EKING_EK08009, + (void *) lcd_ek08009_get_parm); + return ret; +} /* End of lcd_oem_init */ +module_init(lcd_ek08009_init); + +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_EKING_EK08009_C diff --git a/common/wmt_display/devices/lcd-HANNSTAR-HSD101PFW2.c b/common/wmt_display/devices/lcd-HANNSTAR-HSD101PFW2.c new file mode 100755 index 0000000..438e3fe --- /dev/null +++ b/common/wmt_display/devices/lcd-HANNSTAR-HSD101PFW2.c @@ -0,0 +1,103 @@ +/*++ + * linux/drivers/video/wmt/lcd-HANNSTAR-HSD101PFW2.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_EKING_HSD101PFW2_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_HSD101PFW2_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_HSD101PFW2_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +static void lcd_HSD101PFW2_power_on(void); +static void lcd_HSD101PFW2_power_off(void); + +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_parm_t lcd_HSD101PFW2_parm = { + .bits_per_pixel = 18, + .capability = 0, + .vmode = { + .name = "HANNSTAR HSD101PFW2", + .refresh = 60, + .xres = 1024, + .yres = 600, + .pixclock = KHZ2PICOS(45000), + .left_margin = 44, + .right_margin = 88, + .upper_margin = 10, + .lower_margin = 5, + .hsync_len = 44, + .vsync_len = 10, + .sync = FB_SYNC_VERT_HIGH_ACT, + .vmode = 0, + .flag = 0, + }, + .width = 222, + .height = 125, + .initial = lcd_HSD101PFW2_power_on, + .uninitial = lcd_HSD101PFW2_power_off, +}; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +static void lcd_HSD101PFW2_power_on(void) +{ + DPRINT("lcd_HSD101PFW2_power_on\n"); + + /* TODO */ +} + +static void lcd_HSD101PFW2_power_off(void) +{ + DPRINT("lcd_HSD101PFW2_power_off\n"); + + /* TODO */ +} + +struct lcd_parm_t *lcd_HSD101PFW2_get_parm(int arg) +{ + return &lcd_HSD101PFW2_parm; +} + +int lcd_HSD101PFW2_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_HANNSTAR_HSD101PFW2, + (void *) lcd_HSD101PFW2_get_parm); + return ret; +} /* End of lcd_oem_init */ +module_init(lcd_HSD101PFW2_init); + +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_EKING_HSD101PFW2_C diff --git a/common/wmt_display/devices/lcd-INNOLUX-AT070TN83.c b/common/wmt_display/devices/lcd-INNOLUX-AT070TN83.c new file mode 100755 index 0000000..7c1da49 --- /dev/null +++ b/common/wmt_display/devices/lcd-INNOLUX-AT070TN83.c @@ -0,0 +1,118 @@ +/*++ + * linux/drivers/video/wmt/lcd-INNOLUX-AT070TN83.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_INNOLUX_AT070TN83_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_AT070TN83_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_AT070TN83_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +static void lcd_at070tn83_initial(void); +static void lcd_at070tn83_uninitial(void); + +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_parm_t lcd_at070tn83_parm = { + .bits_per_pixel = 18, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "INNOLUX AT707TN83", + .refresh = 60, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(33333), + .left_margin = 45, + .right_margin = 210, + .upper_margin = 22, + .lower_margin = 22, + .hsync_len = 1, + .vsync_len = 1, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 154, + .height = 85, + .initial = lcd_at070tn83_initial, + .uninitial = lcd_at070tn83_uninitial, +}; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +static void lcd_at070tn83_initial(void) +{ +#if 0 + outl(inl(GPIO_BASE_ADDR + 0x80) | BIT0, GPIO_BASE_ADDR + 0x80); + outl(inl(GPIO_BASE_ADDR + 0x4C) | BIT28, GPIO_BASE_ADDR + 0x4C); + outl(inl(GPIO_BASE_ADDR + 0x8C) | BIT28, GPIO_BASE_ADDR + 0x8C); + /* DVDD */ + /* T2 > 0ms */ /* AVDD/VCOM(NANDQS) */ + outl(inl(GPIO_BASE_ADDR + 0xCC) | BIT28, GPIO_BASE_ADDR + 0xCC); + /* T4 > 0ms */ + /* VGH */ + /* 0 < T6 <= 10ms */ + lcd_enable_signal(1); /* signal, DVO enable */ + lcd_oem_enable_backlight(200); /* T12 > 200ms, BL(bit0) */ +#endif +} + +static void lcd_at070tn83_uninitial(void) +{ +#if 0 + /* BL(bit0) */ + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~BIT0, GPIO_BASE_ADDR + 0xC0); + mdelay(200); /* T12 > 200ms */ + lcd_enable_signal(0); /* singal, DVO enable */ + /* AVDD/VCOM(NANDQS) */ + outl(inl(GPIO_BASE_ADDR + 0xCC) & ~BIT28, GPIO_BASE_ADDR + 0xCC); +#endif +} + +struct lcd_parm_t *lcd_at070tn83_get_parm(int arg) +{ + return &lcd_at070tn83_parm; +} + +int lcd_at070tn83_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_INNOLUX_AT070TN83, + (void *) lcd_at070tn83_get_parm); + return ret; +} /* End of lcd_oem_init */ +module_init(lcd_at070tn83_init); + +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_INNOLUX_AT070TN83_C diff --git a/common/wmt_display/devices/lcd-lvds-1024x600.c b/common/wmt_display/devices/lcd-lvds-1024x600.c new file mode 100755 index 0000000..952a276 --- /dev/null +++ b/common/wmt_display/devices/lcd-lvds-1024x600.c @@ -0,0 +1,94 @@ +/*++ + * linux/drivers/video/wmt/lcd-lvds-1024x600.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_LVDS_1024x600_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_LVDS_1024x600_XXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_LVDS_1024x600_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +static void lcd_LVDS_1024x600_initial(void); + +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_parm_t lcd_LVDS_1024x600_parm = { + .bits_per_pixel = 24, + .capability = LCD_CAP_VSYNC_HI, + .vmode = { + .name = "ePAD 1024x600", /* LVDS_1024x600 */ + .refresh = 60, + .xres = 1024, + .yres = 600, + .pixclock = KHZ2PICOS(45000), + .left_margin = 50, + .right_margin = 50, + .upper_margin = 10, + .lower_margin = 10, + .hsync_len = 4, + .vsync_len = 4, + .sync = FB_SYNC_VERT_HIGH_ACT, + .vmode = 0, + .flag = 0, + }, + .width = 222, + .height = 125, + .initial = lcd_LVDS_1024x600_initial, +}; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +static void lcd_LVDS_1024x600_initial(void) +{ + DPRINT("lcd_LVDS_1024x600_initial\n"); + + /* TODO */ +} + +struct lcd_parm_t *lcd_LVDS_1024x600_get_parm(int arg) +{ + return &lcd_LVDS_1024x600_parm; +} + +int lcd_LVDS_1024x600_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_LVDS_1024x600, + (void *) lcd_LVDS_1024x600_get_parm); + return ret; +} /* End of lcd_oem_init */ +module_init(lcd_LVDS_1024x600_init); + +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_1024x600_C diff --git a/common/wmt_display/devices/lcd-mipi-ssd2828.c b/common/wmt_display/devices/lcd-mipi-ssd2828.c new file mode 100755 index 0000000..92d0b98 --- /dev/null +++ b/common/wmt_display/devices/lcd-mipi-ssd2828.c @@ -0,0 +1,375 @@ +/* + * ========================================================================== + * + * Filename: lcd-b079xan01.c + * + * Description: + * + * Version: 0.01 + * Created: Thursday, December 27, 2012 02:50:05 HKT + * + * Author: Sam Mei (), + * Company: + * + * ========================================================================== + */ + +#include <common.h> +#include <command.h> +#include <asm/types.h> +#include <asm/byteorder.h> + +#include "../../../board/wmt/include/wmt_spi.h" +#include "../../../board/wmt/include/wmt_iomux.h" + +#include "../lcd.h" + +#define DELAY_MASK 0xff000000 +#define CHIPSELECT 0 + +extern void spi1_write_then_read_data(unsigned char *wbuf, unsigned char *rbuf, + int num, int clk_mode, int chip_sel); + +static inline void __spi_write(u8 *buf, int len) +{ + spi1_write_then_read_data(buf, buf, sizeof(buf), SPI_MODE_3, CHIPSELECT); + udelay(10); +} + +static void ssd2828_read(uint8_t reg, uint16_t *data) +{ + uint8_t buf1[3] = { 0x70, 0x00, 0x00 }; + uint8_t buf2[3] = { 0x73, 0x00, 0x00 }; + + buf1[2] = reg; + + spi1_write_then_read_data(buf1, buf1, sizeof(buf1), SPI_MODE_3, CHIPSELECT); + udelay(10); + + spi1_write_then_read_data(buf2, buf1, sizeof(buf2), SPI_MODE_3, CHIPSELECT); + udelay(10); + + *data = (buf1[1] << 8) | buf1[2]; +} + +static inline void spi_write_24bit(uint32_t data) +{ + uint8_t buf[3]; + + buf[0] = (data >> 16) & 0xff; + buf[1] = (data >> 8) & 0xff; + buf[2] = data & 0xff; + + __spi_write(buf, 3); +} + +static void ssd2828_reset(void) +{ + gpio_direction_output(14, 1); + mdelay(10); + + gpio_direction_output(WMT_PIN_GP0_GPIO0, 1); + mdelay(10); + gpio_direction_output(WMT_PIN_GP0_GPIO0, 0); + mdelay(20); + gpio_direction_output(WMT_PIN_GP0_GPIO0, 1); + mdelay(20); +} + +// BP080WX7 + +static const uint32_t ssd2828_bp080wx7[] = { + 0x7000B1, // VSA=02 , HSA=02 + 0x720202, + 0x7000B2, // VBP+VSA=8, HBP+HSA=40 + 0x720828, + 0x7000B3, // VFP=04 , HFP=10 + 0x72040A, + 0x7000B4, // HACT=1280 + 0x720500, + 0x7000B5, // vACT=800 + 0x720320, + 0x7000B6, // Non burst mode with sync event 24bpp + 0x720007, + + //DELAY_MASK + 10, + + 0x7000DE, // 4lanes + 0x720003, + 0x7000D6, //BGR + 0x720005, + 0x7000B9, + 0x720000, + + //DELAY_MASK + 10, + 0x7000BA, //PLL=24*16 = 384MHz + 0x72C012, + 0x7000BB, //LP CLK=8.3MHz + 0x720008, + 0x7000B9, + 0x720001, + + //DELAY_MASK + 200, + 0x7000B8, // Virtual Channel 0 + 0x720000, + + 0x7000B7, //LP Mode + 0x720342, + + //DELAY_MASK + 10, + 0x7000BC, + 0x720000, + 0x700011, //sleep out + + DELAY_MASK + 200, + 0x7000BC, + 0x720000, + 0x700029, //display on + + // DELAY_MASK + 50, //Video Mode + 0x7000B7, + 0x72034B, + + DELAY_MASK + 200, + 0x7000BC, + 0x720000, + 0x700029, //display on +}; + +static int bp080wx7_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ssd2828_bp080wx7); i++) { + if ((ssd2828_bp080wx7[i] & DELAY_MASK) == DELAY_MASK) { + mdelay(ssd2828_bp080wx7[i] & 0xff); + } else { + spi_write_24bit(ssd2828_bp080wx7[i]); + } + } + + return 0; +} + +static void lcd_bp080wx7_on(void) +{ + uint16_t id; + + printf("%s\n", __FUNCTION__); + ssd2828_reset(); + + ssd2828_read(0xb0, &id); + if (id == 0x2828) { + printf("found SSD2828!\n"); + bp080wx7_init(); + lcd_enable_signal(1); /* singal on */ + } else + printf("Error: SSD2828 not found! (0x%x)\n", id); +} + +static void lcd_bp080wx7_off(void) +{ + lcd_enable_signal(0); /* singal on */ + printf("lcd_b079xan01_power_off\n"); +} + +//Timing parameter for 3.0" QVGA LCD +#define VBPD (6) +#define VFPD (4) +#define VSPW (2) + +#define HBPD (38) +#define HFPD (10) +#define HSPW (2) + +static struct lcd_parm_t lcd_bp080wx7_parm = { + .bits_per_pixel = 24, + .capability = 0, + .vmode = { + .name = "BP080WX7", + .refresh = 60, + .xres = 1280, + .yres = 800, + .pixclock = KHZ2PICOS(64800), + .left_margin = HBPD, + .right_margin = HFPD, + .upper_margin = VBPD, + .lower_margin = VFPD, + .hsync_len = HSPW, + .vsync_len = VSPW, + .sync = 0, //FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, + .vmode = 0, + .flag = 0, + }, + .initial = lcd_bp080wx7_on, + .uninitial = lcd_bp080wx7_off, +}; + +static struct lcd_parm_t *lcd_bp080wx7_get_parm(int arg) +{ + return &lcd_bp080wx7_parm; +} + +// B079XAN01 + +static const uint32_t ssd2828_b079xan01[] = { + 0x7000B1, //VSA=50, HAS=64 + 0x723240, + 0x7000B2, //VBP=30+50, HBP=56+64 + 0x725078, + 0x7000B3, //VFP=36, HFP=60 + 0x72243C, + 0x7000B4, //HACT=768 + 0x720300, + 0x7000B5, //VACT=1024 + 0x720400, + 0x7000B6, + 0x72000b, //burst mode, 24bpp loosely packed + 0x7000DE, //no of lane=4 + 0x720003, + 0x7000D6, //RGB order and packet number in blanking period + 0x720005, + 0x7000B9, //disable PLL + 0x720000, + 0x7000BA, //lane speed=576 (24MHz * 24 = 576) + 0x728018, //may modify according to requirement, 500Mbps to 560Mbps + 0x7000BB, //LP clock + 0x720008, // 576 / 9 / 8 = 8 MHz + 0x7000B9, //enable PPL + 0x720001, + 0x7000C4, //enable BTA + 0x720001, + 0x7000B7, //enter LP mode + 0x720342, + 0x7000B8, //VC + 0x720000, + 0x7000BC, //set packet size + 0x720000, + 0x700011, //sleep out cmd + + DELAY_MASK + 200, + 0x700029, //display on + DELAY_MASK + 200, + 0x7000B7, //video mode on + 0x72030b, +}; + +static int b079xan01_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ssd2828_b079xan01); i++) { + if ((ssd2828_b079xan01[i] & DELAY_MASK) == DELAY_MASK) { + mdelay(ssd2828_b079xan01[i] & 0xff); + } else { + spi_write_24bit(ssd2828_b079xan01[i]); + } + } + return 0; +} + +static void lcd_b079xan01_initial(void) +{ + uint16_t id; + + printf("%s\n", __FUNCTION__); + ssd2828_reset(); + + ssd2828_read(0xb0, &id); + if (id == 0x2828) { + printf("found SSD2828!\n"); + b079xan01_init(); + lcd_enable_signal(1); /* singal on */ + } else + printf("Error: SSD2828 not found! (0x%x)\n", id); +} + +static void lcd_b079xan01_uninitial(void) +{ + lcd_enable_signal(0); /* singal on */ + printf("lcd_b079xan01_power_off\n"); +} + +static struct lcd_parm_t lcd_b079xan01_parm = { + .bits_per_pixel = 24, + .capability = 0, + .vmode = { + .name = "B079XAN01", + .refresh = 60, + .xres = 768, + .yres = 1024, + .pixclock = KHZ2PICOS(64800), + .left_margin = 56, + .right_margin = 60, + .upper_margin = 30, + .lower_margin = 36, + .hsync_len = 64, + .vsync_len = 50, + .sync = 0, //FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, + .vmode = 0, + .flag = 0, + }, + .initial = lcd_b079xan01_initial, + .uninitial = lcd_b079xan01_uninitial, +}; + +static struct lcd_parm_t *lcd_b079xan01_get_parm(int arg) +{ + return &lcd_b079xan01_parm; +} + +int lcd_ssd2828_init(void) +{ + lcd_panel_register(LCD_B079XAN01, (void *) lcd_b079xan01_get_parm); + lcd_panel_register(LCD_BP080WX7, (void *) lcd_bp080wx7_get_parm); + return 0; +} + +module_init(lcd_ssd2828_init); + +static void ssd2828_register_dump(void) +{ + int reg; + uint16_t data; + + for (reg = 0xb0; reg <= 0xff; reg++) { + ssd2828_read(reg, &data); + printf("reg 0x%02X : 0x%04x\n", reg, data); + } +} + +static int do_b0lcd(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + if (argc == 1) + return 0; + + if (!strcmp(argv[1], "fill")) { + mv_Rect rect; + uint32_t color; + + if (argc != 7) { + printf("hx fill left top right bottom color\n"); + return 0; + } + + rect.left = simple_strtoul(argv[2], NULL, 10); + rect.top = simple_strtoul(argv[3], NULL, 10); + rect.right = simple_strtoul(argv[4], NULL, 10); + rect.bottom = simple_strtoul(argv[5], NULL, 10); + + color = simple_strtoul(argv[6], NULL, 16); + + printf("fill %d %d %d %d 0x%x\n", + rect.left, rect.top, rect.right, rect.bottom, color); + mv_fillRect(&rect, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + } else if (!strcmp(argv[1], "dump")) { + ssd2828_register_dump(); + } + + return 0; +} + +U_BOOT_CMD(b0, 10, 1, do_b0lcd, + "bmp - manipulate BMP image data\n", + "info <imageAddr> - display image info\n" + "bmp display <imageAddr> [x y] - display image at x,y\n"); diff --git a/common/wmt_display/devices/lcd-oem.c b/common/wmt_display/devices/lcd-oem.c new file mode 100755 index 0000000..387f42c --- /dev/null +++ b/common/wmt_display/devices/lcd-oem.c @@ -0,0 +1,408 @@ +/*++ + * linux/drivers/video/wmt/lcd-oem.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_OEM_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../lcd.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_OEM_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_OEM_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ + +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ +#ifdef CONFIG_UBOOT +int lcd_bl_time; +void lcd_uboot_set_backlight(void) +{ + int cur; + do { + wmt_read_ostc(&cur); + } while (cur < lcd_bl_time); + REG32_VAL(GPIO_BASE_ADDR + 0xC0) |= 0x800; /* BL( bit 11 ) */ +} + +#endif + +void lcd_oem_enable_backlight(int wait_ms) +{ +#ifdef CONFIG_UBOOT + wmt_read_ostc(&lcd_bl_time); + lcd_bl_time += (wait_ms * 1000); +#else + mdelay(wait_ms); + REG32_VAL(GPIO_BASE_ADDR + 0xC0) |= 0x800; +#endif +} + +#ifndef CONFIG_VPP_SHENZHEN +static void lcd_oem_initial(void) +{ + outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, GPIO_BASE_ADDR + 0x80); + outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x801, GPIO_BASE_ADDR + 0xC0); + lcd_enable_signal(1); +} + +static void lcd_oem_uninitial(void) +{ + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x801, GPIO_BASE_ADDR + 0xC0); + lcd_enable_signal(0); +} +#endif + +struct lcd_parm_t lcd_oem_parm = { + .bits_per_pixel = 24, + .capability = LCD_CAP_VSYNC_HI, + .vmode = { + .name = "WonderMedia OEM LCD (VGA 1024x768)", + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = KHZ2PICOS(63500), + .left_margin = 152, + .right_margin = 48, + .upper_margin = 23, + .lower_margin = 3, + .hsync_len = 104, + .vsync_len = 4, + .sync = FB_SYNC_VERT_HIGH_ACT, + .vmode = 0, + .flag = 0, + }, + .width = 222, + .height = 125, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_initial, + .uninitial = lcd_oem_uninitial +#endif +}; + +#ifndef CONFIG_VPP_SHENZHEN +static void lcd_oem_1024x600_initial(void) +{ + outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, GPIO_BASE_ADDR + 0x80); + + /* DVDD */ + /* T2 > 0ms */ /* AVDD/VCOM( bit 0 ) */ + outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x01, GPIO_BASE_ADDR + 0xC0); + /* T4 > 0ms */ + /* VGH */ + /* 0 < T6 <= 10ms */ + lcd_enable_signal(1); /* singal, DVO enable */ + mdelay(200); /* T12 > 200ms */ + outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x800, GPIO_BASE_ADDR + 0xC0); +} + +static void lcd_oem_1024x600_uninitial(void) +{ + /* BL( bit 11 ) */ + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x800, GPIO_BASE_ADDR + 0xC0); + mdelay(200); /* T12 > 200ms */ + lcd_enable_signal(0); /* singal, DVO enable */ + /* AVDD/VCOM( bit 0 ) */ + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x01, GPIO_BASE_ADDR + 0xC0); +} +#endif + +struct lcd_parm_t lcd_oem_parm_1024x600 = { + .bits_per_pixel = 24, + .capability = LCD_CAP_VSYNC_HI, + .vmode = { +#if 1 /* 7" HHX070ML208CP21A */ + .name = "HHX070ML208CP21A", + .refresh = 60, + .xres = 1024, + .yres = 600, + .pixclock = KHZ2PICOS(51200), + .left_margin = 140, + .right_margin = 160, + .upper_margin = 20, + .lower_margin = 12, + .hsync_len = 20, + .vsync_len = 3, + .sync = FB_SYNC_VERT_HIGH_ACT, + .vmode = 0, + .flag = 0, +#else + .name = "ePAD 1024x600", /* HannStar HSD070PFW3 */ + .refresh = 60, + .xres = 1024, + .yres = 600, + .pixclock = KHZ2PICOS(45000), + .left_margin = 50, + .right_margin = 50, + .upper_margin = 10, + .lower_margin = 10, + .hsync_len = 4, + .vsync_len = 4, + .sync = FB_SYNC_VERT_HIGH_ACT, + .vmode = 0, + .flag = 0, +#endif + }, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_1024x600_initial, + .uninitial = lcd_oem_1024x600_uninitial, +#endif +}; + +struct lcd_parm_t lcd_oem_parm_1024x768 = { + .bits_per_pixel = 24, + .capability = LCD_CAP_VSYNC_HI, + .vmode = { + .name = "OEM 1024x768", /* VGA 1024x768 */ + .refresh = 60, + .xres = 1024, + .yres = 768, + .pixclock = KHZ2PICOS(63500), + .left_margin = 152, + .right_margin = 48, + .upper_margin = 23, + .lower_margin = 3, + .hsync_len = 104, + .vsync_len = 4, + .sync = FB_SYNC_VERT_HIGH_ACT, + .vmode = 0, + .flag = 0, + }, + .width = 222, + .height = 125, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_initial, + .uninitial = lcd_oem_uninitial +#endif +}; + +struct lcd_parm_t lcd_oem_parm_1366x768 = { + .bits_per_pixel = 18, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "OEM 1366X768", + .refresh = 60, + .xres = 1366, + .yres = 768, + .pixclock = KHZ2PICOS(75440), + .left_margin = 98, + .right_margin = 31, + .upper_margin = 22, + .lower_margin = 4, + .hsync_len = 65, + .vsync_len = 12, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 293, + .height = 164, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_initial, + .uninitial = lcd_oem_uninitial +#endif +}; + +struct lcd_parm_t lcd_oem_parm_480x800 = { + .bits_per_pixel = 18, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "OEM 480x800", + .refresh = 60, + .xres = 480, + .yres = 800, + .pixclock = KHZ2PICOS(27000), + .left_margin = 78, + .right_margin = 78, + .upper_margin = 60, + .lower_margin = 60, + .hsync_len = 4, + .vsync_len = 4, + .sync = 0, + .vmode = 0, + .flag = 0, + }, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_initial, + .uninitial = lcd_oem_uninitial +#endif +}; + +struct lcd_parm_t lcd_oem_parm_800x480 = { + .bits_per_pixel = 18, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "OEM 800x480", + .refresh = 48, + .xres = 800, + .yres = 480, + .pixclock = KHZ2PICOS(27000), + .left_margin = 50, + .right_margin = 50, + .upper_margin = 17, + .lower_margin = 16, + .hsync_len = 10, + .vsync_len = 5, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 154, + .height = 85, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_initial, + .uninitial = lcd_oem_uninitial +#endif +}; + +#ifndef CONFIG_VPP_SHENZHEN +static void lcd_oem_1280x800_initial(void) +{ + DBG_MSG("lcd 10 power sequence\n"); + outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, GPIO_BASE_ADDR + 0x80); + + /* VDD on */ + /* 0 < T < 50ms */ + lcd_enable_signal(1); /* singal on */ + /* VGH,VGL low */ /* AVDD/VCOM( bit 0 ) */ + outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x01, GPIO_BASE_ADDR + 0xC0); + mdelay(150); /* T5 > 120ms */ + outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x800, GPIO_BASE_ADDR + 0xC0); +} + +static void lcd_oem_1280x800_uninitial(void) +{ + /* turn off backlight */ + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x800, GPIO_BASE_ADDR + 0xC0); + mdelay(150); + /* turn off LCD */ + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x01, GPIO_BASE_ADDR + 0xC0); + lcd_enable_signal(0); /* turn off singal */ +} +#endif + +struct lcd_parm_t lcd_oem_parm_800x1280 = { + .bits_per_pixel = 24, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "WY101ML369IN30A", + .refresh = 60, + .xres = 800, + .yres = 1280, + .pixclock = KHZ2PICOS(71100), + .left_margin = 70, + .right_margin = 80, + .upper_margin = 10, + .lower_margin = 10, + .hsync_len = 10, + .vsync_len = 3, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 135, + .height = 217, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_1280x800_initial, + .uninitial = lcd_oem_1280x800_uninitial, +#endif +}; + +struct lcd_parm_t lcd_oem_parm_1280x800 = { + .bits_per_pixel = 24, + .capability = LCD_CAP_CLK_HI, + .vmode = { + .name = "WY101ML369IN30A", + .refresh = 60, + .xres = 1280, + .yres = 800, + .pixclock = KHZ2PICOS(71100), + .left_margin = 70, + .right_margin = 80, + .upper_margin = 10, + .lower_margin = 10, + .hsync_len = 10, + .vsync_len = 3, + .sync = 0, + .vmode = 0, + .flag = 0, + }, + .width = 217, + .height = 135, +#ifndef CONFIG_VPP_SHENZHEN + .initial = lcd_oem_1280x800_initial, + .uninitial = lcd_oem_1280x800_uninitial, +#endif +}; + +/*----------------------- Function Body --------------------------------------*/ +struct lcd_parm_t *lcd_oem_get_parm(int arg) +{ + return &lcd_oem_parm; +} + +int lcd_oem_init(void) +{ + int ret; + + ret = lcd_panel_register(LCD_WMT_OEM, (void *)lcd_oem_get_parm); + return ret; +} /* End of lcd_oem_init */ +module_init(lcd_oem_init); + +struct lcd_parm_t *lcd_get_oem_parm(int resx, int resy) +{ + struct lcd_parm_t *oem_parm[] = { + &lcd_oem_parm_480x800, + &lcd_oem_parm_1024x600, + &lcd_oem_parm_1024x768, + &lcd_oem_parm_1366x768, + &lcd_oem_parm_800x480, + &lcd_oem_parm_800x1280, + &lcd_oem_parm_1280x800, + 0 + }; + struct lcd_parm_t *p; + int i; + + for (i = 0; ; i++) { + p = oem_parm[i]; + if (p == 0) { + p = oem_parm[0]; + break; + } + if ((resx == p->vmode.xres) && (resy == p->vmode.yres)) + break; + } + return p; +} +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_OEM_C diff --git a/common/wmt_display/devices/lcd-setup.c b/common/wmt_display/devices/lcd-setup.c new file mode 100755 index 0000000..6653fdc --- /dev/null +++ b/common/wmt_display/devices/lcd-setup.c @@ -0,0 +1,212 @@ +/* + * ========================================================================== + * + * Filename: lcd-spi.c + * + * Description: + * + * Version: 0.01 + * Created: Thursday, December 27, 2012 02:50:05 HKT + * + * Author: Sam Mei (), + * Company: + * + * ========================================================================== + */ + +#include <common.h> +#include <command.h> +#include <asm/types.h> +#include <asm/errno.h> +#include <asm/byteorder.h> + +#include "../../../board/wmt/include/wmt_spi.h" +#include "../../../board/wmt/include/wmt_iomux.h" + +#include "../lcd.h" + +#define CHIPSELECT 0 + +#ifndef SPI_GPIO +static void spi_ctrl_9bit_tx(u8 val, int cmd_data) +{ + uint8_t buf[2],rbuf[2]; + + if (cmd_data) + buf[0] = (val >> 1) | BIT7; + else + buf[0] = (val >> 1) & 0x7f; + + buf[1] = (val << 7); + + spi_write_then_read_data(buf, rbuf, sizeof(buf), SPI_MODE_1, CHIPSELECT); +} + +#else + +#define CLK WMT_PIN_GP12_SPI0CLK +#define MOSI WMT_PIN_GP12_SPI0MOSI +#define MISO WMT_PIN_GP12_SPI0MISO +#define SS WMT_PIN_GP12_SPI0SS0 + +static void spi_gpio_9bit_tx(u8 val, int cmd_data) +{ + int i; + + // CS + gpio_direction_output(SS, 1); + gpio_direction_output(SS, 0); + + // D/C + gpio_direction_output(MOSI, cmd_data); + gpio_direction_output(CLK, 0); + gpio_direction_output(CLK, 1); + + // 8-bit value + for (i = 7; i >= 0; i--) { + gpio_direction_output(MOSI, !!(val & (1 << i))); + gpio_direction_output(CLK, 0); + gpio_direction_output(CLK, 1); + } + + // CS + gpio_direction_output(SS, 1); +} +#endif + +static inline void spi_9bit_tx(u8 val, int cmd_data) +{ +#ifdef SPI_GPIO + spi_gpio_9bit_tx(val, cmd_data); +#else + spi_ctrl_9bit_tx(val, cmd_data); +#endif +} + +static int ts8224b_cmd(u8 cmd) +{ + spi_9bit_tx(cmd, 0); + return 0; +} + +static int ts8224b_data(u8 data) +{ + spi_9bit_tx(data, 1); + return 0; +} + +/* + * setenv wmt.lcd.setup 0 + * setenv wmt.display.param 2:0:24:1024:600:60 + * setenv wmt.display.tmr 30000:0:78:78:480:78:4:60:800:60 + */ +static int ts8224b_init(void) +{ + + static uint16_t settings[] = { + #include "ts8224b.h" + }; + int i; + + printf(" ## %s \n", __FUNCTION__); + for (i = 0; i < ARRAY_SIZE(settings); i += 2) { + ts8224b_cmd(settings[i] >> 8); + ts8224b_data(settings[i+1]); + } + + ts8224b_cmd(0x11); + mdelay(120); + + ts8224b_cmd(0x29); + mdelay(50); + ts8224b_cmd(0x2c); + return 0; +} + +static int i2c_write(int i2c_idx, uint8_t reg, uint8_t value) +{ + unsigned char data[2] = { reg, value }; + struct i2c_msg_s msg[1] = { + { + .addr = 0xE0 >> 1, + .flags = I2C_M_WR, + .len = 2, + .buf = data, + }, + }; + + if (wmt_i2c_transfer(&msg[0], 1, i2c_idx) > 0) + return 0; + + printf(" ## lcd i2c1 write error %s, %d\n", __func__, __LINE__); + return -1; +} + +static uint8_t init_data[] = { + 0x4b, 0x01, + 0x0c, 0x01, + 0x05, 0x03, + 0x41, 0x03, + 0x10, 0x06, + 0x11, 0xE0, + 0x12, 0x00, + 0x13, 0x3C, + 0x14, 0x06, + 0x15, 0x40, + 0x16, 0x03, + 0x17, 0x9E, + 0x18, 0x00, + 0x19, 0x10, + 0x1a, 0x03, + 0x1b, 0x84, + 0x1c, 0x80, + 0x1d, 0x0A, + 0x1e, 0x80, + 0x1f, 0x06, + 0x3c, 0x17, + 0x3e, 0x16, + 0x36, 0x00, + 0x31, 0x00, + 0x35, 0x41, + 0x30, 0xB0, + 0x30, 0xB1, + 0x00, 0x0B, +}; + +static int chunghwa_init(void) +{ + int i; + + printf(" ## %s, %d\n", __FUNCTION__, __LINE__); + for (i = 0; i < ARRAY_SIZE(init_data); i += 2) { + i2c_write(1, init_data[i], init_data[i+1]); + } + + return 0; +} + +enum { + LCD_SETUP_TS8224B, + LCD_SETUP_CHUNGHWA, + LCD_SETUP_MAX, +}; + +int lcd_spi_setup(void) +{ + int id; + char *s = getenv("wmt.lcd.setup"); + + if (!s) + return -ENODEV; + + id = simple_strtoul(s, NULL, 10); + switch (id) { + case LCD_SETUP_TS8224B: + return ts8224b_init(); + case LCD_SETUP_CHUNGHWA: + return chunghwa_init(); + default: + return -EINVAL; + } +} + diff --git a/common/wmt_display/devices/lcd.c b/common/wmt_display/devices/lcd.c new file mode 100755 index 0000000..2e42a95 --- /dev/null +++ b/common/wmt_display/devices/lcd.c @@ -0,0 +1,448 @@ +/*++ + * linux/drivers/video/wmt/lcd.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LCD_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#ifdef CONFIG_KERNEL +#include <linux/gpio.h> +#endif +#include "../lcd.h" +#include "../vout.h" + +#ifdef CONFIG_VPP_SHENZHEN +#include "../../../board/wmt/include/wmt_iomux.h" +#endif + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define LCD_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LCD_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lcd_xxx_t; *//*Example*/ +struct lcd_device_t { + struct lcd_parm_t* (*get_parm)(int arg); +}; + +/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lcd_xxx; *//*Example*/ +struct lcd_device_t lcd_device_array[LCD_PANEL_MAX]; +int lcd_panel_on = 1; +int lcd_pwm_enable; +enum lcd_panel_t lcd_panel_id = LCD_PANEL_MAX; +int lcd_panel_bpp = 24; + +struct vout_dev_t lcd_vout_dev_ops; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lcd_xxx(void); *//*Example*/ +enum lcd_panel_t lcd_lvds_id = LCD_PANEL_MAX; +int lcd_type; + +/*----------------------- Function Body --------------------------------------*/ +/*----------------------- Backlight --------------------------------------*/ +void lcd_set_type(int type) +{ + lcd_type = type; /* 0-LCD, 1-LVDS */ +} + +int lcd_get_type(void) +{ + return lcd_type; +} + +#ifdef CONFIG_VPP_SHENZHEN + +#define MAX_LCD_GPIO_NUM 5 + +static struct { + int gpio; + int active; +} lcd_power[MAX_LCD_GPIO_NUM] = {{-1, 0}}; + +static int parse_uboot_param(void) +{ + char buf[64]; + unsigned int parm[32]; + int l = sizeof(buf); + int i, gpio_num; + + for(i = 0; i < MAX_LCD_GPIO_NUM; i++) + lcd_power[i].gpio = -1; + + /* + * In hardware, maybe there are several gpio to control LCD power + * We can set the wmt.lcd.power as follows: + * setenv wmt.lcd.power gpio0:active0,gpio1:active1,....,gpio4:active4 + */ + if (wmt_getsyspara("wmt.lcd.power", buf, &l)) { + DBG_ERR("please set wmt.lcd.power\n"); + return -22; + } + + i = vpp_parse_param(buf, parm, 2 * MAX_LCD_GPIO_NUM, 0); + gpio_num = i / 2; + + for(i = 0; i < gpio_num; i++) { + + lcd_power[i].gpio = parm[i * 2]; + lcd_power[i].active = parm[i * 2 + 1]; + + printf("lcd power%d: gpio%d, active %d\n", + i, lcd_power[i].gpio, lcd_power[i].active); + } + + return 0; +} + +void lcd_power_on(bool on) +{ + int i; + + for(i = 0; i < MAX_LCD_GPIO_NUM; i++) { + if (lcd_power[i].gpio < 0) + return; + + gpio_direction_output(lcd_power[i].gpio, on ? + lcd_power[i].active : !lcd_power[i].active); + + DBG_MSG("lcd_power_on: i = %d, on = %d, gpio = %d, active = %d\n", + i, on, lcd_power[i].gpio, lcd_power[i].active); + } +} + +#endif + +void lcd_set_lvds_id(int id) +{ + lcd_lvds_id = id; +} + +int lcd_get_lvds_id(void) +{ + return lcd_lvds_id; +} + +void lcd_set_parm(int id, int bpp) +{ + lcd_panel_id = id; + lcd_panel_bpp = bpp; +} + +struct lcd_parm_t *lcd_get_parm(enum lcd_panel_t id, unsigned int arg) +{ + struct lcd_device_t *p; + + p = &lcd_device_array[id]; + if (p && p->get_parm) + return p->get_parm(arg); + return 0; +} + +struct vout_dev_t *lcd_get_dev(void) +{ + if (lcd_panel_id >= LCD_PANEL_MAX) + return 0; + return &lcd_vout_dev_ops; +} + +#ifdef CONFIG_KERNEL +static DEFINE_SEMAPHORE(lcd_sem); +#endif +void lcd_set_mutex(int lock) +{ +#ifdef CONFIG_KERNEL + if (lock) + down(&lcd_sem); + else + up(&lcd_sem); +#endif +} + +void lcd_set_enable(int enable) +{ + DBG_MSG("%d\n", enable); + if (!p_lcd) + return; + + lcd_set_mutex(1); + if (enable) { + if (p_lcd->initial) + p_lcd->initial(); + else { + lcd_enable_signal(1); /* singal enable */ +#ifndef CONFIG_VPP_SHENZHEN + outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, + GPIO_BASE_ADDR + 0x80); + outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x801, + GPIO_BASE_ADDR + 0xC0); +#endif + } + } else { + if (p_lcd->uninitial) + p_lcd->uninitial(); + else { + lcd_enable_signal(0); /* singal disable */ +#ifndef CONFIG_VPP_SHENZHEN + outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x801, + GPIO_BASE_ADDR + 0xC0); +#endif + } + } + lcd_set_mutex(0); +} + +void lcd_enable_signal(int enable) +{ + int hdmi_off; + + DBG_MSG("%d\n", enable); + if (lcd_get_type()) { /* LVDS */ + /* TODO */ + } else { /* LCD */ + govrh_set_dvo_enable(p_govrh2, enable); + } + + hdmi_off = (govrh_get_MIF_enable(p_govrh)) ? 0 : 1; + vpp_set_clock_enable(DEV_DVO, (hdmi_off && !enable) ? 0 : 1, 1); +} + +#ifdef __KERNEL__ +/*----------------------- LCD --------------------------------------*/ +static int __init lcd_arg_panel_id +( + char *str /*!<; // argument string */ +) +{ + sscanf(str, "%d", (int *) &lcd_panel_id); + if (lcd_panel_id >= LCD_PANEL_MAX) + lcd_panel_id = LCD_PANEL_MAX; + DBGMSG(KERN_INFO "set lcd panel id = %d\n", lcd_panel_id); + return 1; +} /* End of lcd_arg_panel_id */ + +__setup("lcdid=", lcd_arg_panel_id); +#endif +int lcd_panel_register(int no, void (*get_parm)(int mode)) +{ + struct lcd_device_t *p; + + if (no >= LCD_PANEL_MAX) { + DBGMSG(KERN_ERR "*E* lcd device no max is %d !\n", + LCD_PANEL_MAX); + return -1; + } + + p = &lcd_device_array[no]; + if (p->get_parm) { + DBGMSG(KERN_ERR "*E* lcd device %d exist !\n", no); + return -1; + } + p->get_parm = (void *) get_parm; + return 0; +} /* End of lcd_device_register */ + +/*----------------------- vout device plugin --------------------------------*/ +void lcd_set_power_down(int enable) +{ +#ifdef CONFIG_VPP_SHENZHEN + static int save_state = -1; + + if (save_state != enable) { + /* lcd enable control by user */ + lcd_power_on(enable ? 0: 1); + lcd_set_enable(enable ? 0 : 1); + save_state = enable; + } +#endif +} + +#ifdef CONFIG_VPP_SHENZHEN +void lcd_backlight_power_on(int on) +{ + if (parse_backlight_params()) + return; + + if (g_backlight_param.gpio < 0) + return; + + gpio_direction_output(g_backlight_param.gpio, + on ? g_backlight_param.active : !g_backlight_param.active); +} +#endif + +static void wmt_config_govrh_polar(struct vout_t *vo) +{ + /* wmt.display.polar [clock polar]:[hsync polart]:[vsync polar]*/ + char buf[64]; + int l = sizeof(buf); + int clk_pol, hsync_pol, vsync_pol; + unsigned int parm[3]; + + if (wmt_getsyspara("wmt.display.polar", buf, &l)) + return; + + vpp_parse_param(buf, (unsigned int *)parm, 3, 0); + clk_pol = parm[0]; + hsync_pol = parm[1]; + vsync_pol = parm[2]; + DBG_MSG("govrh polar: clk-pol %d, hsync %d, vsync %d\n", + clk_pol, hsync_pol, vsync_pol); + govrh_set_dvo_clock_delay(vo->govr, clk_pol ? 0 : 1, 0); + govrh_set_dvo_sync_polar(vo->govr, + hsync_pol ? 0 : 1, vsync_pol ? 0 : 1); +} + +int lcd_set_mode(unsigned int *option) +{ + struct vout_t *vo; + enum vout_inf_mode_t inf_mode; + + DBG_MSG("option %d,%d\n", option[0], option[1]); + + vo = lcd_vout_dev_ops.vout; + inf_mode = vo->inf->mode; + if (option) { + unsigned int capability; + + if (lcd_panel_id == 0) + p_lcd = lcd_get_oem_parm(vo->resx, vo->resy); + else + p_lcd = lcd_get_parm(lcd_panel_id, lcd_panel_bpp); + + if (!p_lcd) { + DBG_ERR("lcd %d not support\n", lcd_panel_id); + return -1; + } + DBG_MSG("[%s] %s (id %d,bpp %d)\n", vout_inf_str[inf_mode], + p_lcd->vmode.name, lcd_panel_id, lcd_panel_bpp); + capability = p_lcd->capability; + switch (inf_mode) { + case VOUT_INF_LVDS: + lvds_set_sync_polar( + (capability & LCD_CAP_HSYNC_HI) ? 0 : 1, + (capability & LCD_CAP_VSYNC_HI) ? 0 : 1); + lvds_set_rgb_type(lcd_panel_bpp); + break; + case VOUT_INF_DVI: + govrh_set_dvo_clock_delay(vo->govr, + (capability & LCD_CAP_CLK_HI) ? 0 : 1, 0); + govrh_set_dvo_sync_polar(vo->govr, + (capability & LCD_CAP_HSYNC_HI) ? 0 : 1, + (capability & LCD_CAP_VSYNC_HI) ? 0 : 1); + switch (lcd_panel_bpp) { + case 15: + govrh_IGS_set_mode(vo->govr, 0, 1, 1); + break; + case 16: + govrh_IGS_set_mode(vo->govr, 0, 3, 1); + break; + case 18: + govrh_IGS_set_mode(vo->govr, 0, 2, 1); + break; + case 24: + govrh_IGS_set_mode(vo->govr, 0, 0, 0); + break; + default: + break; + } + break; + default: + break; + } + } else + p_lcd = 0; + + wmt_config_govrh_polar(vo); + return 0; +} + +int lcd_check_plugin(int hotplug) +{ + return (p_lcd) ? 1 : 0; +} + +int lcd_get_edid(char *buf) +{ + return 1; +} + +int lcd_config(struct vout_info_t *info) +{ + info->resx = p_lcd->vmode.xres; + info->resy = p_lcd->vmode.yres; + info->fps = p_lcd->vmode.refresh; + return 0; +} + +int lcd_init(struct vout_t *vo) +{ + DBG_MSG("%d\n", lcd_panel_id); + + /* vo_set_lcd_id(LCD_CHILIN_LW0700AT9003); */ + if (lcd_panel_id >= LCD_PANEL_MAX) + return -1; + + if (lcd_panel_id == 0) + p_lcd = lcd_get_oem_parm(vo->resx, vo->resy); + else + p_lcd = lcd_get_parm(lcd_panel_id, 24); + + if (p_lcd == 0) + return -1; + + /* set default parameters */ + vo->resx = p_lcd->vmode.xres; + vo->resy = p_lcd->vmode.yres; + vo->pixclk = PICOS2KHZ(p_lcd->vmode.pixclock) * 1000; + return 0; +} + +struct vout_dev_t lcd_vout_dev_ops = { + .name = "LCD", + .mode = VOUT_INF_DVI, + .capability = VOUT_DEV_CAP_FIX_RES + VOUT_DEV_CAP_FIX_PLUG, + + .init = lcd_init, + .set_power_down = lcd_set_power_down, + .set_mode = lcd_set_mode, + .config = lcd_config, + .check_plugin = lcd_check_plugin, + .get_edid = lcd_get_edid, +}; + +int lcd_module_init(void) +{ + parse_uboot_param(); + + vout_device_register(&lcd_vout_dev_ops); + return 0; +} /* End of lcd_module_init */ +module_init(lcd_module_init); +/*--------------------End of Function Body -----------------------------------*/ +#undef LCD_C diff --git a/common/wmt_display/devices/sil902x.c b/common/wmt_display/devices/sil902x.c new file mode 100755 index 0000000..186bb02 --- /dev/null +++ b/common/wmt_display/devices/sil902x.c @@ -0,0 +1,74 @@ +/*++ + * linux/drivers/video/wmt/sil902x.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define SIL902X_C +/*--------------------------------------------------------------------* +SiI902x Software customization for PC platform. +Based on : + Video input configuration= + 24 bit RGB in + Hsync + Vsync + DE + PCLK + rising edge is the 1st clock after DE=High + Audio input configuration= + SPDIF, word size, sample frequency all refer to stream header + + SiI902x i2c device address=0x72. ( CI2CA pin=LOW) +//================== i2c routine ========================= +SiI902x i2c max speed is 100KHz. +A version max speed is 400KHz + +Data = I2C_ReadByte(TX_SLAVE_ADDR, RegOffset); +I2C_WriteByte(TPI_BASE_ADDR, RegOffset, Data); +I2C_WriteBlock(TPI_BASE_ADDR, TPI_Offset, pData, NBytes); +I2C_ReadBlock(TPI_BASE_ADDR, TPI_Offset, pData, NBytes); + +------------------------------------------------------------------------------*/ +//#define DEBUG +//#define DEBUG_DETAIL +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../vout.h" +#include "sil902x.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define SIL902X_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define SIL902X_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx sil902x_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in sil902x.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int sil902x_xxx; *//*Example*/ + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void sil902x_xxx(void); *//*Example*/ +int sil902x_module_init(void) +{ +// vout_device_register(&sil902x_vout_dev_ops); + return 0; +} /* End of sil902x_module_init */ +module_init(sil902x_module_init); +/*--------------------End of Function Body -----------------------------------*/ +#undef SIL902X_C + diff --git a/common/wmt_display/devices/sil902x.h b/common/wmt_display/devices/sil902x.h new file mode 100755 index 0000000..a7e0f0d --- /dev/null +++ b/common/wmt_display/devices/sil902x.h @@ -0,0 +1,71 @@ +/*++ + * linux/drivers/video/wmt/devices/sil902x.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef SIL902X_H +/* To assert that only one occurrence is included */ +#define SIL902X_H +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ + +/* following is the C++ header */ +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* #define SIL902X_XXXX 1 *//*Example*/ +#define SIL902X_STATUS_ARG_NUM 3 + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void sil902x_xxx_t; *//*Example*/ +typedef struct { + int (*init)(void); + int (*poll)(void); + void (*cp_enable)(int enable); + void (*get_status)(int *arg); + void (*config)(int vic); +} sil902x_ko_ops_t; + +/*-------------------- EXPORTED PRIVATE VARIABLES -----------------------------*/ +#ifdef SIL902X_C /* allocate memory for variables only in xxx.c */ +#define EXTERN +#else +#define EXTERN extern +#endif /* ifdef SIL902X_C */ + +/* EXTERN int sil902x_xxx; *//*Example*/ +EXTERN void sil902x_init_module(int ko); +EXTERN int sil902x_enable_access(void); +EXTERN int sil902x_get_cp_support(void); + +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS -------------------------------*/ +/* #define SIL902X_XXX_YYY xxxx *//*Example*/ +/*--------------------- EXPORTED PRIVATE FUNCTIONS ---------------------------*/ +/* extern void sil902x_xxx(void); *//*Example*/ + +#ifdef __cplusplus +} +#endif +#endif /* ifndef SIL902X_H */ + diff --git a/common/wmt_display/devices/ts8224b.h b/common/wmt_display/devices/ts8224b.h new file mode 100755 index 0000000..8786628 --- /dev/null +++ b/common/wmt_display/devices/ts8224b.h @@ -0,0 +1,446 @@ +#ifndef _TS8224B_H_ +#define _TS8224B_H_ + +//Enable Page1 hsd4.0 +0xFF00, 0x55, +0xFF01, 0xAA, +0xFF02, 0x52, +0xFF03, 0x08, +0xFF04, 0x80, + +0xF200, 0x00, +0xF201, 0x84, +0xF202, 0x02, + +0xF40A, 0x13, + +0xF000, 0x55, +0xF001, 0xAA, +0xF002, 0x52, +0xF003, 0x08, +0xF004, 0x01, + +0xB000, 0x0D, +0xB001, 0x0D, +0xB002, 0x0D, + +0xB600, 0x34, +0xB601, 0x34, +0xB602, 0x34, + +0xB100, 0x0D, +0xB101, 0x0D, +0xB102, 0x0D, + +// AVEE: manual, -6V : -2.5xVCI) +0xB700, 0x34, +0xB701, 0x34, +0xB702, 0x34, + +//Power Control for VCL +0xB200, 0x00, +0xB201, 0x00, +0xB202, 0x00, + +0xB800, 0x24, +0xB801, 0x24, +0xB802, 0x24, + +// VGH: Clamp Enable, 2*AVDD-AVEE, //11V +0xBF00, 0X01, + +0xB300, 0x0F, +0xB301, 0x0F, +0xB302, 0x0F, + +0xB900, 0x34,//34 +0xB901, 0x34, +0xB902, 0x34, + +// VGL_REG(VGLO):-10V +0xB500, 0x08, +0xB501, 0x08, +0xB502, 0x08, + +0xC200, 0x03, + +//VGL(LVGL): +0xBA00, 0x24, +0xBA01, 0x24, +0xBA02, 0x24, + + +// VGMP/VGSP: 4.8v +0xBC00, 0X00, +0xBC01, 0x78, +0xBC02, 0X00, + +// VGMN/VGSN -4.8v +0xBD00, 0x00, +0xBD01, 0x78, +0xBD02, 0x00, + +// VCOM=-0.1 +0xBE00, 0x00, +0xBE01, 0x80, //2f +//R+ +0xD100, 0x00, +0xD101, 0x05, +0xD102, 0x00, +0xD103, 0x06, +0xD104, 0x00, +0xD105, 0x0E, +0xD106, 0x00, +0xD107, 0x19, +0xD108, 0x00, +0xD109, 0x29, +0xD10A, 0x00, +0xD10B, 0x55, +0xD10C, 0x00, +0xD10D, 0x80, +0xD10E, 0x00, +0xD10F, 0xC7, +0xD110, 0x00, +0xD111, 0xFC, +0xD112, 0x01, +0xD113, 0x48, +0xD114, 0x01, +0xD115, 0x7C, +0xD116, 0x01, +0xD117, 0xC5, +0xD118, 0x01, +0xD119, 0xFE, +0xD11A, 0x02, +0xD11B, 0x00, +0xD11C, 0x02, +0xD11D, 0x30, +0xD11E, 0x02, +0xD11F, 0x60, +0xD120, 0x02, +0xD121, 0x7A, +0xD122, 0x02, +0xD123, 0x9A, +0xD124, 0x02, +0xD125, 0xAC, +0xD126, 0x02, +0xD127, 0xC4, +0xD128, 0x02, +0xD129, 0xD3, +0xD12A, 0x02, +0xD12B, 0xE9, +0xD12C, 0x02, +0xD12D, 0xF8, +0xD12E, 0x03, +0xD12F, 0x0D, +0xD130, 0x03, +0xD131, 0x3B, +0xD132, 0x05, +0xD133, 0xB5, +//G+ +0xD200, 0x00, +0xD201, 0x05, +0xD202, 0x00, +0xD203, 0x06, +0xD204, 0x00, +0xD205, 0x0E, +0xD206, 0x00, +0xD207, 0x19, +0xD208, 0x00, +0xD209, 0x29, +0xD20A, 0x00, +0xD20B, 0x55, +0xD20C, 0x00, +0xD20D, 0x80, +0xD20E, 0x00, +0xD20F, 0xC7, +0xD210, 0x00, +0xD211, 0xFC, +0xD212, 0x01, +0xD213, 0x48, +0xD214, 0x01, +0xD215, 0x7C, +0xD216, 0x01, +0xD217, 0xC5, +0xD218, 0x01, +0xD219, 0xFE, +0xD21A, 0x02, +0xD21B, 0x00, +0xD21C, 0x02, +0xD21D, 0x30, +0xD21E, 0x02, +0xD21F, 0x60, +0xD220, 0x02, +0xD221, 0x7A, +0xD222, 0x02, +0xD223, 0x9A, +0xD224, 0x02, +0xD225, 0xAC, +0xD226, 0x02, +0xD227, 0xC4, +0xD228, 0x02, +0xD229, 0xD3, +0xD22A, 0x02, +0xD22B, 0xE9, +0xD22C, 0x02, +0xD22D, 0xF8, +0xD22E, 0x03, +0xD22F, 0x0D, +0xD230, 0x03, +0xD231, 0x3B, +0xD232, 0x05, +0xD233, 0xB5, +//B+ +0xD300, 0x00, +0xD301, 0x05, +0xD302, 0x00, +0xD303, 0x06, +0xD304, 0x00, +0xD305, 0x0E, +0xD306, 0x00, +0xD307, 0x19, +0xD308, 0x00, +0xD309, 0x29, +0xD30A, 0x00, +0xD30B, 0x55, +0xD30C, 0x00, +0xD30D, 0x80, +0xD30E, 0x00, +0xD30F, 0xC7, +0xD310, 0x00, +0xD311, 0xFC, +0xD312, 0x01, +0xD313, 0x48, +0xD314, 0x01, +0xD315, 0x7C, +0xD316, 0x01, +0xD317, 0xC5, +0xD318, 0x01, +0xD319, 0xFE, +0xD31A, 0x02, +0xD31B, 0x00, +0xD31C, 0x02, +0xD31D, 0x30, +0xD31E, 0x02, +0xD31F, 0x60, +0xD320, 0x02, +0xD321, 0x7A, +0xD322, 0x02, +0xD323, 0x9A, +0xD324, 0x02, +0xD325, 0xAC, +0xD326, 0x02, +0xD327, 0xC4, +0xD328, 0x02, +0xD329, 0xD3, +0xD32A, 0x02, +0xD32B, 0xE9, +0xD32C, 0x02, +0xD32D, 0xF8, +0xD32E, 0x03, +0xD32F, 0x0D, +0xD330, 0x03, +0xD331, 0x3B, +0xD332, 0x05, +0xD333, 0xB5, +//R- +0xD400, 0x00, +0xD401, 0x05, +0xD402, 0x00, +0xD403, 0x06, +0xD404, 0x00, +0xD405, 0x0E, +0xD406, 0x00, +0xD407, 0x19, +0xD408, 0x00, +0xD409, 0x29, +0xD40A, 0x00, +0xD40B, 0x55, +0xD40C, 0x00, +0xD40D, 0x80, +0xD40E, 0x00, +0xD40F, 0xC7, +0xD410, 0x00, +0xD411, 0xFC, +0xD412, 0x01, +0xD413, 0x48, +0xD414, 0x01, +0xD415, 0x7C, +0xD416, 0x01, +0xD417, 0xC5, +0xD418, 0x01, +0xD419, 0xFE, +0xD41A, 0x02, +0xD41B, 0x00, +0xD41C, 0x02, +0xD41D, 0x30, +0xD41E, 0x02, +0xD41F, 0x60, +0xD420, 0x02, +0xD421, 0x7A, +0xD422, 0x02, +0xD423, 0x9A, +0xD424, 0x02, +0xD425, 0xAC, +0xD426, 0x02, +0xD427, 0xC4, +0xD428, 0x02, +0xD429, 0xD3, +0xD42A, 0x02, +0xD42B, 0xE9, +0xD42C, 0x02, +0xD42D, 0xF8, +0xD42E, 0x03, +0xD42F, 0x0D, +0xD430, 0x03, +0xD431, 0x3B, +0xD432, 0x05, +0xD433, 0xB5, +//G- +0xD500, 0x00, +0xD501, 0x05, +0xD502, 0x00, +0xD503, 0x06, +0xD504, 0x00, +0xD505, 0x0E, +0xD506, 0x00, +0xD507, 0x19, +0xD508, 0x00, +0xD509, 0x29, +0xD50A, 0x00, +0xD50B, 0x55, +0xD50C, 0x00, +0xD50D, 0x80, +0xD50E, 0x00, +0xD50F, 0xC7, +0xD510, 0x00, +0xD511, 0xFC, +0xD512, 0x01, +0xD513, 0x48, +0xD514, 0x01, +0xD515, 0x7C, +0xD516, 0x01, +0xD517, 0xC5, +0xD518, 0x01, +0xD519, 0xFE, +0xD51A, 0x02, +0xD51B, 0x00, +0xD51C, 0x02, +0xD51D, 0x30, +0xD51E, 0x02, +0xD51F, 0x60, +0xD520, 0x02, +0xD521, 0x7A, +0xD522, 0x02, +0xD523, 0x9A, +0xD524, 0x02, +0xD525, 0xAC, +0xD526, 0x02, +0xD527, 0xC4, +0xD528, 0x02, +0xD529, 0xD3, +0xD52A, 0x02, +0xD52B, 0xE9, +0xD52C, 0x02, +0xD52D, 0xF8, +0xD52E, 0x03, +0xD52F, 0x0D, +0xD530, 0x03, +0xD531, 0x3B, +0xD532, 0x05, +0xD533, 0xB5, +//B- +0xD600, 0x00, +0xD601, 0x05, +0xD602, 0x00, +0xD603, 0x06, +0xD604, 0x00, +0xD605, 0x0E, +0xD606, 0x00, +0xD607, 0x19, +0xD608, 0x00, +0xD609, 0x29, +0xD60A, 0x00, +0xD60B, 0x55, +0xD60C, 0x00, +0xD60D, 0x80, +0xD60E, 0x00, +0xD60F, 0xC7, +0xD610, 0x00, +0xD611, 0xFC, +0xD612, 0x01, +0xD613, 0x48, +0xD614, 0x01, +0xD615, 0x7C, +0xD616, 0x01, +0xD617, 0xC5, +0xD618, 0x01, +0xD619, 0xFE, +0xD61A, 0x02, +0xD61B, 0x00, +0xD61C, 0x02, +0xD61D, 0x30, +0xD61E, 0x02, +0xD61F, 0x60, +0xD620, 0x02, +0xD621, 0x7A, +0xD622, 0x02, +0xD623, 0x9A, +0xD624, 0x02, +0xD625, 0xAC, +0xD626, 0x02, +0xD627, 0xC4, +0xD628, 0x02, +0xD629, 0xD3, +0xD62A, 0x02, +0xD62B, 0xE9, +0xD62C, 0x02, +0xD62D, 0xF8, +0xD62E, 0x03, +0xD62F, 0x0D, +0xD630, 0x03, +0xD631, 0x3B, +0xD632, 0x05, +0xD633, 0xB5, + +//Enable Page0 +0xF000, 0x55, +0xF001, 0xAA, +0xF002, 0x52, +0xF003, 0x08, +0xF004, 0x00, + + +0xB100, 0xcc, +0xB101, 0x00, + +0xB600, 0x05, + +//// Gate EQ: +0xB700, 0x70, +0xB701, 0x70, + +//// Source EQ: +0xB800, 0x01, +0xB801, 0x03, +0xB802, 0x03, +0xB803, 0x03, + +// #Inversion mode (2-dot) +0xBC00, 0x02, +0xBC01, 0x00, +0xBC02, 0x00, + +// Timing control 4H w/ 4-delay +0xC900, 0xD0, +0xC901, 0x02, +0xC902, 0x50, +0xC903, 0x50, +0xC904, 0x50, +// Display Timing: + +0x3600, 0x00, +0x3500, 0x00, + +0x3a00, 0x66, + +#endif diff --git a/common/wmt_display/devices/vt1625.c b/common/wmt_display/devices/vt1625.c new file mode 100755 index 0000000..35b60d7 --- /dev/null +++ b/common/wmt_display/devices/vt1625.c @@ -0,0 +1,949 @@ +/*++ + * linux/drivers/video/wmt/vt1625.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define VT1625_C +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../vout.h" + +#ifdef CONFIG_KERNEL +#include <linux/workqueue.h> +#endif + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define VT1625_XXXX xxxx *//*Example*/ +#ifdef CONFIG_KERNEL +#define CONFIG_VT1625_INTERRUPT +#endif +#define CONFIG_VT1625_POWER +#define CONFIG_VM700 + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define VT1625_XXXX 1 *//*Example*/ +#define VT1625_ADDR 0x40 + +enum { + VT1625_INPUT_SELECTION = 0x00, + VT1625_SYNC_SELECTION_0 = 0x01, + VT1625_SYNC_SELECTION_1 = 0x02, + VT1625_FILTER_SELECTION = 0x03, + VT1625_OUTPUT_MODE = 0x04, + VT1625_CLOCK_CONTROL = 0x05, + + /* start position & overflow */ + VT1625_OVERFLOW = 0x06, + VT1625_START_ACTIVE_VIDEO = 0x07, + VT1625_START_HORIZONTAL_POSITION = 0x08, + VT1625_START_VERTICAL_POSITION = 0x09, + + /* amplitude factor */ + VT1625_CR_AMPLITUDE_FACTOR = 0x0A, + VT1625_BLACK_LEVEL = 0x0B, + VT1625_Y_AMPLITUDE_FACTOR = 0x0C, + VT1625_CB_AMPLITUDE_FACTOR = 0x0D, + + VT1625_POWER_MANAGEMENT = 0x0E, + VT1625_STATUS = 0x0F, + + /* Hue */ + VT1625_HUE_ADJUSTMENT = 0x10, + VT1625_OVERFLOW_MISC = 0x11, + + /* PLL */ + VT1625_PLL_P2 = 0x12, + VT1625_PLL_D = 0x13, + VT1625_PLL_N = 0x14, + VT1625_PLL_OVERFLOW = 0x15, + + /* Sub Carrier */ + VT1625_SUBCARRIER_VALUE_0 = 0x16, + VT1625_SUBCARRIER_VALUE_1 = 0x17, + VT1625_SUBCARRIER_VALUE_2 = 0x18, + VT1625_SUBCARRIER_VALUE_3 = 0x19, + + VT1625_VERSION_ID = 0x1B, + VT1625_DAC_OVERFLOW = 0x1C, + + /* test */ + VT1625_TEST_0 = 0x1D, + VT1625_TEST_1 = 0x1E, + + VT1625_FILTER_SWITCH = 0x1F, + VT1625_TV_SYNC_STEP = 0x20, + VT1625_TV_BURST_ENVELOPE_STEP = 0x21, + VT1625_TV_SUB_CARRIER_PHASE_ADJUST = 0x22, + VT1625_TV_BLANK_LEVEL = 0x23, + VT1625_TV_SIGNAL_OVERFLOW = 0x24, + + /* DAC & GPO */ + VT1625_DAC_SELECTION_0 = 0x4A, + VT1625_DAC_SELECTION_1 = 0x4B, + VT1625_GPO = 0x4C, + + VT1625_COLBAR_LUMA_DELAY = 0x4D, + VT1625_UV_DELAY = 0x4E, + VT1625_BURST_MAX_AMPLITUDE = 0x4F, + + /* Graphic timing */ + VT1625_GRAPHIC_H_TOTAL = 0x50, + VT1625_GRAPHIC_H_ACTIVE = 0x51, + VT1625_GRAPHIC_H_OVERFLOW = 0x52, + VT1625_GRAPHIC_V_TOTAL = 0x53, + VT1625_GRAPHIC_V_OVERFLOW = 0x54, + + /* TV timing */ + VT1625_TV_H_TOTAL = 0x55, + VT1625_TV_H_ACTIVE = 0x56, + VT1625_TV_H_SYNC_WIDTH = 0x57, + VT1625_TV_H_OVERFLOW = 0x58, + VT1625_TV_BURST_START = 0x59, + VT1625_TV_BURST_END = 0x5A, + VT1625_TV_VIDEO_START = 0x5B, + VT1625_TV_VIDEO_END = 0x5C, + VT1625_TV_VIDEO_OVERFLOW = 0x5D, + + /* scale factor */ + VT1625_V_SCALE_FACTOR = 0x5E, + VT1625_H_SCALE_FACTOR = 0x5F, + VT1625_SCALE_OVERFLOW = 0x60, + VT1625_H_BLUR_SCALE_OVERFLOW = 0x61, + VT1625_ADAPTIVE_DEFLICKER_THR = 0x62, + VT1625_SCALE_H_TOTAL = 0x63, + VT1625_SCALE_H_TOTAL_OVERFLOW = 0x64, + + /* Amplitude factor */ + VT1625_PY_AMP_FACTOR = 0x65, + VT1625_PB_AMP_FACTOR = 0x66, + VT1625_PR_AMP_FACTOR = 0x67, + + VT1625_POST_ADJUST = 0x68, + VT1625_AUTO_CORRECT_SENSE = 0x69, + + /* WSS 0x6A - 0x73 */ + VT1625_INT_WSS_2 = 0x71, + + /* Close Caption 0x74 - 0x7A */ + + /* Signature Value 0x7B - 0x82 */ +} vt1625_reg_t; + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx vt1625_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in vt1625.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int vt1625_xxx; *//*Example*/ + +static char vt1625_ntsc_param[] = { + 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x82, /* 00 - 07 */ +#ifdef CONFIG_VM700 + 0x14, 0x05, 0x6E, 0x15, 0x51, 0x50, 0x37, 0xB7, /* 08 - 0f */ + 0x00, 0x80, 0x04, 0x08, 0x08, 0x90, 0xD6, 0x7B, /* 10 - 17 */ +#else + 0x14, 0x05, 0x6E, 0x15, 0x52, 0x4E, 0x37, 0xB7, /* 08 - 0f */ + 0x08, 0x80, 0x04, 0x08, 0x08, 0x90, 0xD6, 0x7B, /* 10 - 17 */ +#endif + 0xF0, 0x21, 0x02, 0x50, 0x43, 0x80, 0x00, 0xFC, /* 18 - 1f */ + 0x16, 0x08, 0xDC, 0x7D, 0x02, 0x56, 0x33, 0x8F, /* 20 - 27 */ + 0x58, 0x00, 0x00, 0xA6, 0x29, 0xD4, 0x81, 0x00, /* 28 - 2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38 - 3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 40 - 47 */ +#ifdef CONFIG_VM700 + 0x00, 0x00, 0xC5, 0x0F, 0x08, 0x01, 0x01, 0x43, /* 48 - 4f */ +#else + 0x00, 0x00, 0xC5, 0x0F, 0x00, 0x01, 0x10, 0x44, /* 48 - 4f */ +#endif + 0x59, 0xCF, 0x23, 0x0C, 0x02, 0x59, 0xCF, 0x7F, /* 50 - 57 */ + 0x23, 0x94, 0xD6, 0x00, 0x9C, 0x06, 0x00, 0x00, /* 58 - 5f */ + 0x80, 0x28, 0xFF, 0x59, 0x03, 0x55, 0x56, 0x56, /* 60 - 67 */ + 0x00, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* 68 - 6f */ + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 - 77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78 - 7f */ + 0x00, 0x00, 0x00 +}; + +static char vt1625_pal_param[] = { + 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x8C, /* 00 - 07 */ +#ifdef CONFIG_VM700 + 0x0E, 0x01, 0x6E, 0x00, 0x51, 0x50, 0x37, 0xB7, /* 08 - 0f */ + 0x00, 0x80, 0x04, 0x08, 0x08, 0x90, 0xCB, 0x8A, /* 10 - 17 */ +#else + 0x0E, 0x01, 0x7a, 0x00, 0x55, 0x58, 0x37, 0xB7, /* 08 - 0f */ + 0xff, 0x87, 0x04, 0x08, 0x08, 0x90, 0xCB, 0x8A, /* 10 - 17 */ +#endif + 0x09, 0x2A, 0x06, 0x50, 0x41, 0x80, 0x00, 0xFC, /* 18 - 1f */ + 0x17, 0x0C, 0x4E, 0x76, 0x02, 0x5F, 0x34, 0x8C, /* 20 - 27 */ + 0x4F, 0x5E, 0x15, 0xA2, 0x22, 0x80, 0xD3, 0x10, /* 28 - 2f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 37 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38 - 3f */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 40 - 47 */ +#ifdef CONFIG_VM700 + 0x00, 0x00, 0xC5, 0x0F, 0x08, 0x02, 0x01, 0x43, /* 48 - 4f */ +#else + 0x00, 0x00, 0xC5, 0x0F, 0x00, 0x02, 0x10, 0x4C, /* 48 - 4f */ +#endif + 0x5f, 0xCF, 0x23, 0x70, 0x02, 0x5F, 0xD0, 0x7F, /* 50 - 57 */ + 0x23, 0x92, 0xCE, 0xDF, 0xA0, 0x06, 0x00, 0x00, /* 58 - 5f */ + 0x80, 0x20, 0xFF, 0x5F, 0x03, 0x5f, 0x00, 0x00, /* 60 - 67 */ + 0x00, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* 68 - 6f */ + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 - 77 */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78 - 7f */ + 0x00, 0x00, 0x00 +}; + +enum vt1625_out_t { + VT1625_OUT_CVBS, + VT1625_OUT_YUV, + VT1625_OUT_VGA, + VT1625_OUT_MAX +}; + +enum vt1625_out_t vt1625_out_mode; + +int vt1625_tv_mode; +vdo_color_fmt vt1625_colfmt; + +static int pre_plugin; + +/* +* VT1625 U-Boot Env to Set Register +*/ +typedef struct { + unsigned char offset; + unsigned char value; +} vt1625_reg_env_t; + +#define VT1625_REG_MAX_OFFSET 0x82 /* Register Offset: 0x00 ~ 0x82 */ +/* +* setenv wmt.vt1625.pal.reg regOffset1=regValue1,regOffset2=regValue2,... +* for example: +* setenv wmt.vt1625.pal.reg 0a=75,0c=53,23=7a,4f=48 +* setenv wmt.vt1625.ntsc.reg 0a=75,0c=53,23=7a,4f=48 +*/ +#define VT1625_PAL_REG_ENV "wmt.vt1625.pal.reg" +#define VT1625_NTSC_REG_ENV "wmt.vt1625.ntsc.reg" + +/* +* setenv wmt.vt1625.cvbs.always.turnon 1 +* The cvbs is always turned on event if the av line is pluged out +* setenv wmt.vt1625.cvbs.always.turnon 0 +* The cvbs is turned on if the av line is pluged in. +* And the cvbs is turned off if the av line is pluged out +*/ +#define VT1625_CVBS_ALWAYS_TURNON "wmt.vt1625.cvbs.always.turnon" + +static int vt1625_cvbs_always_turnon; + +#ifdef CONFIG_KERNEL +/* +* VT1625 Timer to Monitor Register +*/ +/* +* Monitor the vt1625 register for avoiding the register is cleared. +* setenv wmt.vt1625.reg.monitor 1 +* +* If the wmt.vt1625.reg.monitor is Not set or set to 0, +* it will not monitor the register +* +*/ +#define VT1625_REG_MONITOR_ENV "wmt.vt1625.reg.monitor" + +#define VT1625_TIMER_INTERVAL 1000 // 1000 ms + +static struct timer_list vt1625_timer; +static struct work_struct vt1625_work; + +static void vt1625_set_tv_mode(int ntsc); + +#endif + +#ifdef CONFIG_UBOOT +#define msleep mdelay +#endif + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void vt1625_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +/* +* Function: register_is_right() +* Parametr: +* ntsc = 0: PAL +* ntsc = 1: NTSC +* Return : +* 0: the register's values is wrong +* 1: the register's values is right +*/ +static int register_is_right(int ntsc) +{ + int i; + char buf[32]; + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INPUT_SELECTION, buf, 32); + + for(i = 0; i < 32; i++) { + /* + * reg 0x0E is power management register. Skip it + * reg 0x0F is status register. it is volatile. Skip it + */ + if(i == 14 || i == 15) + continue; + + + if(i == 0) { + if(vt1625_colfmt == VDO_COL_FMT_YUV444) { + if(buf[0] != 0x3A) + break; + } else { + if(buf[0] != 0x03) + break; + } + } else { + if(ntsc) { + /* + * NTSC + */ + if(buf[i] != vt1625_ntsc_param[i]) + break; + } else { + /* + * PAL + */ + if(buf[i] != vt1625_pal_param[i]) + break; + } + } + } + + if(i != 32) + return 0; + else + return 1; +} + +#ifdef CONFIG_KERNEL +static void vt1625_reconfig(struct work_struct *work) +{ + int right; + + if(vt1625_tv_mode) { + right = register_is_right((vt1625_tv_mode == 1) ? 1 : 0); + if(right == 0) { + DBG_ERR("VT1625 Reg Error, re-init the register\n"); + + vt1625_set_tv_mode((vt1625_tv_mode == 1) ? 1 : 0); + } + } + + mod_timer(&vt1625_timer, jiffies + msecs_to_jiffies(VT1625_TIMER_INTERVAL)); +} + +static DECLARE_WORK(vt1625_work, vt1625_reconfig); + +static void vt1625_config_timer(unsigned long fcontext) +{ + schedule_work(&vt1625_work); +} + +static void init_vt1625_timer(void) +{ + char buf[40]; + int varlen = 40; + char *endp; + int value, reg_monitor; + + reg_monitor = 0; + + if (wmt_getsyspara(VT1625_REG_MONITOR_ENV, buf, &varlen) == 0) { + value = simple_strtoul(buf, &endp, 0); + if( value != 0) + reg_monitor = 1; + } + + if(reg_monitor) { + init_timer(&vt1625_timer); + vt1625_timer.function = vt1625_config_timer; + vt1625_timer.data = 0; + } else + vt1625_timer.function = NULL; + +} + +static void start_vt1625_timer(void) +{ + if(vt1625_timer.function) + mod_timer(&vt1625_timer, jiffies + msecs_to_jiffies(VT1625_TIMER_INTERVAL)); +} + +static void stop_vt1625_timer(void) +{ + if(vt1625_timer.function) + del_timer_sync(&vt1625_timer); +} +#endif + +/* +* Function : vt1625_parse_reg_env +* Parameter: +* p_env : env name +* p_reg : store the vt1625 register offset and value +* p_regnum: register number +* Return: +* 0 : the env is set and the env's value is available +* -1 : the env is Not set or the env's value is wrong +* -12 : no memory for parsing register env +*/ +static int vt1625_parse_reg_env(char *p_env, + vt1625_reg_env_t *p_reg, int *p_regnum) +{ + int i; + char *buf; + int buflen = 1024; + unsigned int value; + const char *p; + char *endp; + + buf = kmalloc(buflen, GFP_KERNEL); + if(buf == NULL) { + DBG_ERR("kzalloc fail\n"); + return -12; + } + + if(wmt_getsyspara(p_env, buf, &buflen) != 0) { + kfree(buf); + return -1; + } + + *p_regnum = 0; + p = buf; + + for(i = 0; i <= VT1625_REG_MAX_OFFSET; i++) { + value = simple_strtoul(p, &endp, 16); + if(value > VT1625_REG_MAX_OFFSET) { + DBG_ERR("wrong register offset\n"); + kfree(buf); + return -1; + } + (p_reg + i)->offset = value; + /* + * reg_offset must be followed reg_value + * If reg_offset is NOT followed any reg_value, It is wrong format + */ + if(*endp == '\0'|| *(endp + 1) == '\0') { + DBG_ERR("wrong env(%s) format\n", p_env); + kfree(buf); + return -1; + } + + p = endp + 1; + + value = simple_strtoul(p, &endp, 16); + if(value > 0xFF) { + DBG_ERR("wrong register value\n"); + kfree(buf); + return -1; + } + (p_reg + i)->value = value; + *p_regnum = *p_regnum + 1; + + if(*endp == '\0') + break; + + p = endp + 1; + } + + kfree(buf); + return 0; +} + +/*the define and struct i2c_msg were declared int linux/i2c.h*/ +void vt1625_reg_dump(void) +{ + int i; + char buf[256]; + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INPUT_SELECTION, + buf, 128); + for (i = 0; i < 128; i += 8) { + MSG("0x%02X : 0x%02X,0x%02X,0x%02X,0x%02X", + i, buf[i], buf[i + 1], buf[i + 2], buf[i + 3]); + MSG(",0x%02X,0x%02X,0x%02X,0x%02X\n", + buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]); + } +} + +static char vt1625_get_dac_val(enum vt1625_out_t mode) +{ + char ret; + + switch (mode) { + case VT1625_OUT_CVBS: + ret = 0x37; + break; + case VT1625_OUT_VGA: + ret = 0x38; + break; + case VT1625_OUT_YUV: + default: + ret = 0x0; + break; + } + return ret; +} + +static void vt1625_set_tv_mode(int ntsc) +{ + char *p; + char buf[10]; + +/* + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INPUT_SELECTION, buf, 5); + DBG_MSG("ntsc %d, 0x%x, 0x%x\n", ntsc, buf[0], buf[4]); + vt1625_tv_mode = (ntsc) ? 1 : 2; +#ifdef CONFIG_KERNEL + if (buf[0] && (vt1625_out_mode != VT1625_OUT_MAX)) { + if (ntsc && !(buf[4] & BIT0)) + return; + if (!ntsc && (buf[4] & BIT0)) + return; + } +#endif +*/ + vt1625_tv_mode = (ntsc) ? 1 : 2; + if(register_is_right(ntsc)) + return; + + DBG_MSG("tv %s,mode %d\n", (ntsc) ? "NTSC" : "PAL", vt1625_out_mode); + + p = (char *)((ntsc) ? vt1625_ntsc_param : vt1625_pal_param); + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INPUT_SELECTION, + &p[VT1625_INPUT_SELECTION], 0x71); + if (vt1625_out_mode == VT1625_OUT_MAX) { /* not stable so no use */ + buf[0] = 0x0; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, buf, 1); + mdelay(10); + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_STATUS, buf, 1); + vt1625_out_mode = (buf[0] & 0x7) ? + VT1625_OUT_CVBS : VT1625_OUT_VGA; + DBG_MSG("get out mode %d, 0x%x\n", vt1625_out_mode, buf[0]); + } + + if (vt1625_out_mode == VT1625_OUT_VGA) { + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_SYNC_SELECTION_1, buf, 1); + buf[0] |= 0xA0; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_SYNC_SELECTION_1, buf, 1); + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_DAC_OVERFLOW, buf, 1); + buf[0] |= 0x20; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_DAC_OVERFLOW, buf, 1); + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_TEST_1, buf, 1); + buf[0] |= 0x40; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_TEST_1, buf, 1); + } else { +#ifdef CONFIG_VT1625_INTERRUPT + /* interrupt (VGA no work) */ + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INT_WSS_2, buf, 1); + buf[0] |= 0xA0; /* enable sense interrupt */ + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INT_WSS_2, buf, 1); +#endif + } + + if (vt1625_colfmt == VDO_COL_FMT_YUV444) { + /* + * Force write reg0x00 and reg0x4C + */ + buf[0] = 0x3A; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INPUT_SELECTION, buf, 1); + buf[0] = 0x08; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_GPO, buf, 1); + } + +#ifdef CONFIG_VT1625_POWER + buf[0] = vt1625_get_dac_val(vt1625_out_mode); + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, buf, 1); +#endif +} + +static int vt1625_check_plugin(int hotplug) +{ + char buf[2]; + char cur[1]; + int plugin; + + /* + * Enable VT1625 Power First + */ + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, cur, 1); + + buf[0] = vt1625_get_dac_val(vt1625_out_mode); + + if(cur[0] != buf[0]) { + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, buf, 1); + + msleep(10); + } + + if((vt1625_out_mode == VT1625_OUT_CVBS) && vt1625_cvbs_always_turnon) + return 1; + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_POWER_MANAGEMENT, + buf, 2); + plugin = ~buf[1] & (~buf[0] & 0x3F); + DBG_MSG("[VT1625] DAC A %d, B %d, C %d, D %d, E %d, F %d\n", + (plugin & 0x20) ? 1 : 0, (plugin & 0x10) ? 1 : 0, + (plugin & 0x08) ? 1 : 0, (plugin & 0x04) ? 1 : 0, + (plugin & 0x02) ? 1 : 0, (plugin & 0x01) ? 1 : 0); + return (plugin) ? 1 : 0; +} + +static int vt1625_init(struct vout_t *vo) +{ + char buf[40]; + int varlen = 40; + char *endp; + unsigned int value; + + DBG_MSG("\n"); + +#ifndef CONFIG_UBOOT + if (vt1625_tv_mode) { /* resume reinit */ + MSG("[VT1625] DVI reinit\n"); + vt1625_set_tv_mode((vt1625_tv_mode == 1) ? 1 : 0); + if (govrh_get_dvo_enable(p_govrh2) == 0) + govrh_set_dvo_enable(p_govrh2, VPP_FLAG_ENABLE); + pre_plugin = 0; + return 0; + } +#endif + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_VERSION_ID, buf, 1); + if (buf[0] != 0x50) /* check version id */ + return -1; + + if (wmt_getsyspara("wmt.display.vt1625.mode", buf, &varlen) == 0) { + if (memcmp(buf, "yuv", 3) == 0) + vt1625_out_mode = VT1625_OUT_YUV; + else if (memcmp(buf, "vga", 3) == 0) + vt1625_out_mode = VT1625_OUT_VGA; + else + vt1625_out_mode = VT1625_OUT_CVBS; + DPRINT("[VT1625] mode %d\n", vt1625_out_mode); + } else + vt1625_out_mode = VT1625_OUT_CVBS; /* VT1625_OUT_MAX; */ + +#ifdef CONFIG_VM700 + vt1625_colfmt = VDO_COL_FMT_YUV444; +#else + vt1625_colfmt = VDO_COL_FMT_ARGB; +#endif + if (wmt_getsyspara("wmt.display.vt1625.colfmt", buf, &varlen) == 0) { + if (memcmp(buf, "yuv", 3) == 0) + vt1625_colfmt = VDO_COL_FMT_YUV444; + else if (memcmp(buf, "rgb", 3) == 0) + vt1625_colfmt = VDO_COL_FMT_ARGB; + } + + vo->option[0] = (unsigned int) vt1625_colfmt; + vo->option[1] = (unsigned int) VPP_DATAWIDHT_12; + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INPUT_SELECTION, buf, 5); + if (buf[0]) + vt1625_tv_mode = (buf[4]) ? 2 : 1; + + p_govrh2->fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255; + + if (wmt_getsyspara(VT1625_CVBS_ALWAYS_TURNON, buf, &varlen) == 0) { + value = simple_strtoul(buf, &endp, 0); + if(value != 0) + vt1625_cvbs_always_turnon = 1; + else + vt1625_cvbs_always_turnon = 0; + } else + vt1625_cvbs_always_turnon = 0; + +#ifdef CONFIG_KERNEL + vt1625_set_tv_mode((vt1625_tv_mode == 1) ? 1 : 0); + + start_vt1625_timer(); +#endif + + MSG("[VT1625] DVI ext device\n"); + return 0; +} + +static int vt1625_set_mode(unsigned int *option) +{ +#ifdef CONFIG_VT1625_INTERRUPT + char buf[1]; +#endif + + DBG_MSG("\n"); +#ifdef CONFIG_VT1625_INTERRUPT + if (!g_vpp.dvi_int_disable) { + vout_set_int_type(1); + vout_set_int_enable(1); + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INT_WSS_2, buf, 1); + buf[0] |= 0xA0; /* enable sense interrupt */ + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_INT_WSS_2, buf, 1); + } +#endif + return 0; +} + +static void vt1625_set_power_down(int enable) +{ + struct vout_t *vo; + char buf[1]; + char cur[1]; + + /* + bit 0-2 : DAC D/E/F - VGA + bit 3 : DAC C - CVBS + bit 3-5 : DAC A/B/C - YPbPr + bit 6 : PLL + bit 7 : IO pad + */ + vo = vout_get_entry(VPP_VOUT_NUM_DVI); + if (vo->status & (VPP_VOUT_STS_BLANK + VPP_VOUT_STS_POWERDN)) + enable = 1; + + /* power down for not support resolution */ +//#ifndef CONFIG_VT1625_INTERRUPT + if ((vt1625_tv_mode != 0) && enable && g_vpp.dvi_int_disable) + buf[0] = 0xFF; + else +//#endif + buf[0] = vt1625_get_dac_val(vt1625_out_mode); + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, cur, 1); + + if (cur[0] == buf[0]) + return; + + DBG_MSG("enable %d,cur 0x%x,new 0x%x\n", enable, cur[0], buf[0]); +#if 1 + if (enable == 0) { + cur[0] &= ~0x40; /* turn on PLL */ + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, cur, 1); + mdelay(3); + + cur[0] &= ~0x80; /* turn on IO pad */ + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, cur, 1); + mdelay(3); + } +#endif +#ifdef CONFIG_VT1625_POWER + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, buf, 1); +#endif +} + +static int vt1625_config(struct vout_info_t *info) +{ + int ntsc = -1; + + DBG_MSG("%d,%d\n", info->resx, info->resy); + if (info->resx == 720) { + switch (info->resy) { + case 480: + ntsc = 1; + break; + case 576: + ntsc = 0; + break; + default: + break; + } + } + + if (ntsc != -1) + vt1625_set_tv_mode(ntsc); + else + vt1625_tv_mode = 0; + DBG_MSG("end\n"); + return 0; +} + +static int vt1625_get_edid(char *buf) +{ + return 0; +} + +#ifdef CONFIG_VT1625_INTERRUPT +static int vt1625_interrupt(void) +{ + char buf[1]; + + vppif_reg32_write(GPIO_BASE_ADDR + 0x4c0, 0x1 << VPP_VOINT_NO, + VPP_VOINT_NO, 0x0); /* GPIO pull-up */ + /* interrupt */ + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INT_WSS_2, buf, 1); + DBG_MSG("0x%x\n", buf[0]); + buf[0] &= ~0x40; /* clear interrupt */ + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INT_WSS_2, buf, 1); + return vt1625_check_plugin(1); +} +#endif + +static void vt1625_poll(void) +{ + int plugin; + char buf[1]; + char cur[1]; + + if (govrh_get_dvo_enable(p_govrh2) == 0) + govrh_set_dvo_enable(p_govrh2, VPP_FLAG_ENABLE); + + plugin = vt1625_check_plugin(0); + if (plugin != pre_plugin) { + struct vout_t *vo; + + vo = vout_get_entry(VPP_VOUT_NUM_DVI); + vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin); +#ifdef CONFIG_KERNEL + vpp_netlink_notify_plug(VPP_VOUT_NUM_DVI, plugin); +#endif + pre_plugin = plugin; + DMSG("%d\n", plugin); + } + + /* + * Disable VT1625 Power if CVBS Not plugin + */ + if(plugin == 0) { + vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, cur, 1); + + buf[0] = 0xFF; + + if(cur[0] != buf[0]) { + vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, + VT1625_POWER_MANAGEMENT, buf, 1); + } + } +} + +static int vt1625_suspend(void) +{ + DMSG("\n"); + +#ifdef CONFIG_KERNEL + stop_vt1625_timer(); +#endif + + return 0; +} + +static int vt1625_resume(void) +{ + DMSG("\n"); + +#ifdef CONFIG_KERNEL + start_vt1625_timer(); +#endif + return 0; +} + +/*----------------------- vout device plugin ---------------------------------*/ +struct vout_dev_t vt1625_vout_dev_ops = { + .name = "VT1625", + .mode = VOUT_INF_DVI, + + .init = vt1625_init, + .set_power_down = vt1625_set_power_down, + .set_mode = vt1625_set_mode, + .config = vt1625_config, + .check_plugin = vt1625_check_plugin, + .get_edid = vt1625_get_edid, +#ifdef CONFIG_VT1625_INTERRUPT + .interrupt = vt1625_interrupt, +#endif + .poll = vt1625_poll, + .suspend = vt1625_suspend, + .resume = vt1625_resume, +}; + +int vt1625_module_init(void) +{ + vt1625_reg_env_t *p_reg; + int i, ret, regnum; + + p_reg = kmalloc((VT1625_REG_MAX_OFFSET + 1) * sizeof(vt1625_reg_env_t), + GFP_KERNEL); + if(p_reg) { + ret = vt1625_parse_reg_env(VT1625_PAL_REG_ENV, p_reg, ®num); + if(ret == 0) { + for(i = 0; i < regnum; i++) + vt1625_pal_param[(p_reg + i)->offset] = + (p_reg + i)->value; + } + + ret = vt1625_parse_reg_env(VT1625_NTSC_REG_ENV, p_reg, ®num); + if(ret == 0) { + for(i = 0; i < regnum; i++) + vt1625_ntsc_param[(p_reg + i)->offset] = + (p_reg + i)->value; + } + + kfree(p_reg); + } else + DBG_ERR("kzalloc fail\n"); + +#ifdef CONFIG_KERNEL + init_vt1625_timer(); +#endif + + vout_device_register(&vt1625_vout_dev_ops); + + return 0; +} +module_init(vt1625_module_init); +/*--------------------End of Function Body -----------------------------------*/ +#undef VT1625_C diff --git a/common/wmt_display/devices/vt1632.c b/common/wmt_display/devices/vt1632.c new file mode 100755 index 0000000..b3950c0 --- /dev/null +++ b/common/wmt_display/devices/vt1632.c @@ -0,0 +1,157 @@ +/*++ + * linux/drivers/video/wmt/vt1632.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define VT1632_C +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "../vout.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define VT1632_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define VT1632_XXXX 1 *//*Example*/ +#define VT1632_ADDR 0x10 + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx vt1632_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in vt1632.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int vt1632_xxx; *//*Example*/ +static int vt1632_not_ready; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void vt1632_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ + +/*the define and struct i2c_msg were declared int linux/i2c.h*/ +int vt1632_check_plugin(int hotplug) +{ + char buf[1]; + int plugin; + + if (vt1632_not_ready) + return 1; + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x9, buf, 1); + plugin = (buf[0] & 0x4) ? 1 : 0; + DPRINT("[VT1632] DVI plug%s\n", (plugin) ? "in" : "out"); + vout_set_int_type(4); + return plugin; +} + +int vt1632_init(struct vout_t *vo) +{ + char buf[16]; + + vt1632_not_ready = 1; + vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x0, buf, 2); + if ((buf[0] != 0x06) || (buf[1] != 0x11)) /* check vender id */ + return -1; + vt1632_not_ready = 0; + + buf[0x0] = 0x37; + buf[0x1] = 0x20; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 2); + DPRINT("[VT1632] DVI ext device\n"); + return 0; +} + +int vt1632_set_mode(unsigned int *option) +{ + char buf[1]; + vpp_datawidht_t dwidth; + + if (vt1632_not_ready) + return -1; + + dwidth = option[1] & BIT0; + DBGMSG("vt1632_set_mode(%d)\n", (dwidth) ? 24 : 12); + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1); + if (dwidth == VPP_DATAWIDHT_12) { + buf[0] &= ~BIT2; + buf[0] |= BIT3; + } else { + buf[0] |= BIT2; + buf[0] &= ~BIT3; + } + vpp_i2c_write(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1); + return 0; +} + +void vt1632_set_power_down(int enable) +{ + char buf[1]; + + if (vt1632_not_ready) + return; + + DBGMSG("vt1632_set_power_down(%d)\n", enable); + + vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1); + if (enable) + buf[0] &= ~BIT0; + else + buf[0] |= BIT0; + vpp_i2c_write(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1); +} + +int vt1632_config(struct vout_info_t *info) +{ + return 0; +} + +int vt1632_get_edid(char *buf) +{ + return 0; +} + +int vt1632_interrupt(void) +{ + return vt1632_check_plugin(1); +} +/*----------------------- vout device plugin ---------------------------------*/ +struct vout_dev_t vt1632_vout_dev_ops = { + .name = "VT1632", + .mode = VOUT_INF_DVI, + + .init = vt1632_init, + .set_power_down = vt1632_set_power_down, + .set_mode = vt1632_set_mode, + .config = vt1632_config, + .check_plugin = vt1632_check_plugin, + .get_edid = vt1632_get_edid, + .interrupt = vt1632_interrupt, +}; + +int vt1632_module_init(void) +{ + vout_device_register(&vt1632_vout_dev_ops); + return 0; +} /* End of vt1632_module_init */ +module_init(vt1632_module_init); +/*--------------------End of Function Body -----------------------------------*/ +#undef VT1632_C diff --git a/common/wmt_display/display_aligment.S b/common/wmt_display/display_aligment.S new file mode 100755 index 0000000..285a922 --- /dev/null +++ b/common/wmt_display/display_aligment.S @@ -0,0 +1,482 @@ +/******************************************************************************* + Copyright (c) 2008 WonderMedia Technologies, Inc. + + Module Name: + + $Workfile: display_aligment.S $ + + Abstract: + + Memory copy with aligment issue + + Registers using: + r0: source address + r1: destination address + r2: len +*******************************************************************************/ + + .text + .code 32 + + .global byte1_alig_mem_copy + .type byte1_alig_mem_copy, %function + .global byte1_less_bundle_copy + .type byte1_less_bundle_copy, %function + + .global byte2_alig_mem_copy + .type byte2_alig_mem_copy, %function + .global byte2_less_bundle_copy + .type byte2_less_bundle_copy, %function + + .global byte3_alig_mem_copy + .type byte3_alig_mem_copy, %function + .global byte3_less_bundle_copy + .type byte3_less_bundle_copy, %function + + .global mem_copy + .type mem_copy, %function + .global less_mem_copy + .type less_mem_copy, %function + + .global bit24_to_bit16_ali24 + .type bit24_to_bit16_ali24, %function + .global bit24_to_bit16_ali32 + .type bit24_to_bit16_ali32, %function +byte1_alig_mem_copy: + stmfd sp!, {r0-r12} +byte1cpy_loop: + ldmia r0!, {r3-r11} // r3-r10 store + mov r12, r4 // backup r4 + mov r3, r3, lsr #8 + mov r12, r12, lsl #24 + orr r3, r3, r12 // r3 shift + + mov r12, r5 // backup r5 + mov r4, r4, lsr #8 + mov r12, r12, lsl #24 + orr r4, r4, r12 // r4 shift + + mov r12, r6 // backup r6 + mov r5, r5, lsr #8 + mov r12, r12, lsl #24 + orr r5, r5, r12 // r5 shift + + mov r12, r7 // backup r7 + mov r6, r6, lsr #8 + mov r12, r12, lsl #24 + orr r6, r6, r12 // r6 shift + + mov r12, r8 // backup r8 + mov r7, r7, lsr #8 + mov r12, r12, lsl #24 + orr r7, r7, r12 // r7 shift + + mov r12, r9 // backup r9 + mov r8, r8, lsr #8 + mov r12, r12, lsl #24 + orr r8, r8, r12 // r8 shift + + mov r12, r10 // backup r10 + mov r9, r9, lsr #8 + mov r12, r12, lsl #24 + orr r9, r9, r12 // r9 shift + + mov r12, r11 // backup r11 + mov r10, r10, lsr #8 + mov r12, r12, lsl #24 + orr r10, r10, r12 // r10 shift + + stmia r1!, {r3-r10} + sub r0, r0, #4 // back to 32 bundle + subs r2, r2, #32 + bne byte1cpy_loop + ldmfd sp!, {r0-r12} + mov pc, lr + +byte1_less_bundle_copy: + stmfd sp!, {r0-r4} +byte1cpy_less_loop: + ldmia r0!, {r3-r4} // r3 + mov r12, r4 // backup r4 + mov r3, r3, lsr #8 + mov r12, r12, lsl #24 + orr r3, r3, r12 // r3 shift + stmia r1!, {r3} + sub r0, r0, #4 + subs r2, r2, #4 + bne byte1cpy_less_loop + ldmfd sp!, {r0-r4} + mov pc, lr + +byte2_alig_mem_copy: + stmfd sp!, {r0-r12} +byte2cpy_loop: + ldmia r0!, {r3-r11} // r3-r10 store + mov r12, r4 // backup r4 + mov r3, r3, lsr #16 + mov r12, r12, lsl #16 + orr r3, r3, r12 // r3 shift + + mov r12, r5 // backup r5 + mov r4, r4, lsr #16 + mov r12, r12, lsl #16 + orr r4, r4, r12 // r4 shift + + mov r12, r6 // backup r6 + mov r5, r5, lsr #16 + mov r12, r12, lsl #16 + orr r5, r5, r12 // r5 shift + + mov r12, r7 // backup r7 + mov r6, r6, lsr #16 + mov r12, r12, lsl #16 + orr r6, r6, r12 // r6 shift + + mov r12, r8 // backup r8 + mov r7, r7, lsr #16 + mov r12, r12, lsl #16 + orr r7, r7, r12 // r7 shift + + mov r12, r9 // backup r9 + mov r8, r8, lsr #16 + mov r12, r12, lsl #16 + orr r8, r8, r12 // r8 shift + + mov r12, r10 // backup r10 + mov r9, r9, lsr #16 + mov r12, r12, lsl #16 + orr r9, r9, r12 // r9 shift + + mov r12, r11 // backup r11 + mov r10, r10, lsr #16 + mov r12, r12, lsl #16 + orr r10, r10, r12 // r10 shift + + stmia r1!, {r3-r10} + sub r0, r0, #4 // back to 32 bundle + subs r2, r2, #32 + bne byte2cpy_loop + ldmfd sp!, {r0-r12} + mov pc, lr + +byte2_less_bundle_copy: + stmfd sp!, {r0-r4} +byte2cpy_less_loop: + ldmia r0!, {r3-r4} // r3 + mov r12, r4 // backup r4 + mov r3, r3, lsr #16 + mov r12, r12, lsl #16 + orr r3, r3, r12 // r3 shift + stmia r1!, {r3} + sub r0, r0, #4 + subs r2, r2, #4 + bne byte2cpy_less_loop + ldmfd sp!, {r0-r4} + mov pc, lr + +byte3_alig_mem_copy: + stmfd sp!, {r0-r12} +byte3cpy_loop: + ldmia r0!, {r3-r11} // r3-r10 store + mov r12, r4 // backup r4 + mov r3, r3, lsr #24 + mov r12, r12, lsl #8 + orr r3, r3, r12 // r3 shift + + mov r12, r5 // backup r5 + mov r4, r4, lsr #24 + mov r12, r12, lsl #8 + orr r4, r4, r12 // r4 shift + + mov r12, r6 // backup r6 + mov r5, r5, lsr #24 + mov r12, r12, lsl #8 + orr r5, r5, r12 // r5 shift + + mov r12, r7 // backup r7 + mov r6, r6, lsr #24 + mov r12, r12, lsl #8 + orr r6, r6, r12 // r6 shift + + mov r12, r8 // backup r8 + mov r7, r7, lsr #24 + mov r12, r12, lsl #8 + orr r7, r7, r12 // r7 shift + + mov r12, r9 // backup r9 + mov r8, r8, lsr #24 + mov r12, r12, lsl #8 + orr r8, r8, r12 // r8 shift + + mov r12, r10 // backup r10 + mov r9, r9, lsr #24 + mov r12, r12, lsl #8 + orr r9, r9, r12 // r9 shift + + mov r12, r11 // backup r11 + mov r10, r10, lsr #24 + mov r12, r12, lsl #8 + orr r10, r10, r12 // r10 shift + + stmia r1!, {r3-r10} + sub r0, r0, #4 // back to 32 bundle + subs r2, r2, #32 + bne byte3cpy_loop + ldmfd sp!, {r0-r12} + mov pc, lr + +byte3_less_bundle_copy: + stmfd sp!, {r0-r4} +byte3cpy_less_loop: + ldmia r0!, {r3-r4} // r3 + mov r12, r4 // backup r4 + mov r3, r3, lsr #24 + mov r12, r12, lsl #8 + orr r3, r3, r12 // r3 shift + stmia r1!, {r3} + sub r0, r0, #4 + subs r2, r2, #4 + bne byte3cpy_less_loop + ldmfd sp!, {r0-r4} + mov pc, lr + +mem_copy: + stmfd sp!, {r0-r10} +ali_mem_copy: + ldmia r0!, {r3-r10} + stmia r1!, {r3-r10} + subs r2, r2, #32 + bne ali_mem_copy + ldmfd sp!, {r0-r10} + mov pc, lr + +less_mem_copy: + stmfd sp!, {r0-r3} +ali_less_mem_copy: + ldmia r0!, {r3} + stmia r1!, {r3} + subs r2, r2, #4 + bne ali_less_mem_copy + ldmfd sp!, {r0-r3} + mov pc, lr + +bit24_to_bit16_ali24: + stmfd sp!, {r0-r11} +bit24_to_bit16_ali24_loop: + ldmia r1!, {r3-r8} + // r11 : final data + // r10 : tmp_reg + mov r11, #0 + + // handle first 16bits ================ + ldr r9, =0xFF + and r10, r3, r9 //B + lsr r10, #3 + mov r11, r10 + + ldr r9, =0xFF00 + and r10, r3, r9 //G + lsr r10, #10 + lsl r10, #5 + orr r11, r11, r10 + + ldr r9, =0xFF0000 + and r10, r3, r9 //R + lsr r10, #19 + lsl r10, #11 + orr r11, r11, r10 + + // handle second 16bits ================ + ldr r9, =0xFF000000 + and r10, r3, r9 //B + lsr r10, #27 + lsl r10, #16 + orr r11, r11, r10 + + ldr r9, =0xFF + and r10, r4, r9 //G + lsr r10, #2 + lsl r10, #21 + orr r11, r11, r10 + + ldr r9, =0xFF00 + and r10, r4, r9 //R + lsr r10, #11 + lsl r10, #27 + orr r11, r11, r10 + mov r3, r11 + + // handle third 16bits ================ + mov r11, #0 + ldr r9, =0xFF0000 + and r10, r4, r9 //B + lsr r10, #19 + orr r11, r11, r10 + + ldr r9, =0xFF000000 + and r10, r4, r9 //G + lsr r10, #26 + lsl r10, #5 + orr r11, r11, r10 + + ldr r9, =0xFF + and r10, r5, r9 //R + lsr r10, #3 + lsl r10, #11 + orr r11, r11, r10 + + // handle forth 16bits ================ + ldr r9, =0xFF00 + and r10, r5, r9 //B + lsr r10, #11 + lsl r10, #16 + orr r11, r11, r10 + + ldr r9, =0xFF0000 + and r10, r5, r9 //G + lsr r10, #18 + lsl r10, #21 + orr r11, r11, r10 + + ldr r9, =0xFF000000 + and r10, r5, r9 //R + lsr r10, #27 + lsl r10, #27 + orr r11, r11, r10 + mov r4, r11 + + // handle fivth 16bits ================ + ldr r9, =0xFF + and r10, r6, r9 //B + lsr r10, #3 + mov r11, r10 + + ldr r9, =0xFF00 + and r10, r6, r9 //G + lsr r10, #10 + lsl r10, #5 + orr r11, r11, r10 + + ldr r9, =0xFF0000 + and r10, r6, r9 //R + lsr r10, #19 + lsl r10, #11 + orr r11, r11, r10 + + // handle sixth 16bits ================ + ldr r9, =0xFF000000 + and r10, r6, r9 //B + lsr r10, #27 + lsl r10, #16 + orr r11, r11, r10 + + ldr r9, =0xFF + and r10, r7, r9 //G + lsr r10, #2 + lsl r10, #21 + orr r11, r11, r10 + + ldr r9, =0xFF00 + and r10, r7, r9 //R + lsr r10, #11 + lsl r10, #27 + orr r11, r11, r10 + mov r5, r11 + + // handle seventh 16bits ================ + mov r11, #0 + ldr r9, =0xFF0000 + and r10, r7, r9 //B + lsr r10, #19 + orr r11, r11, r10 + + ldr r9, =0xFF000000 + and r10, r7, r9 //G + lsr r10, #26 + lsl r10, #5 + orr r11, r11, r10 + + ldr r9, =0xFF + and r10, r8, r9 //R + lsr r10, #3 + lsl r10, #11 + orr r11, r11, r10 + + // handle eighth 16bits ================ + ldr r9, =0xFF00 + and r10, r8, r9 //B + lsr r10, #11 + lsl r10, #16 + orr r11, r11, r10 + + ldr r9, =0xFF0000 + and r10, r8, r9 //G + lsr r10, #18 + lsl r10, #21 + orr r11, r11, r10 + + ldr r9, =0xFF000000 + and r10, r8, r9 //R + lsr r10, #27 + lsl r10, #27 + orr r11, r11, r10 + mov r6, r11 + + stmia r0!, {r3-r6} + subs r2, r2, #24 + bne bit24_to_bit16_ali24_loop + ldmfd sp!, {r0-r11} + mov pc, lr + +bit24_to_bit16_ali32: + stmfd sp!, {r0-r11} +bit24_to_bit16_ali32_copy: + ldmia r1!, {r3-r8} + // r11 : final data + // r10 : tmp_reg + // handle first 32bits ================ + ldr r9, =0xffffff + and r11, r9, r3 + // handle second 32bits ================ + mov r10, r3, lsr #24 + mov r3, r11 + mov r9, r4 //backup r4 + lsl r4, #16 + lsr r4, #8 + orr r4, r4, r10 + // handle third 32bits ================ + lsr r9, #16 + mov r10, r5 //backup r5 + lsl r5, #24 + lsr r5, #8 + orr r5, r5, r9 + // handle fourth 32bits ================ + lsr r10, #8 + stmia r0!, {r3-r5, r10} + + // handle fiveth 32bits ================ + ldr r9, =0xffffff + and r11, r9, r6 + // handle sixth 32bits ================ + mov r10, r6, lsr #24 + mov r6, r11 + mov r9, r7 //backup r7 + lsl r7, #16 + lsr r7, #8 + orr r7, r7, r10 + // handle seventh 32bits ================ + lsr r9, #16 + mov r10, r8 //backup r8 + lsl r8, #24 + lsr r8, #8 + orr r8, r8, r9 + // handle eigth 32bits ================ + lsr r10, #8 + stmia r0!, {r6-r8, r10} + + subs r2, r2, #24 + bne bit24_to_bit16_ali32_copy + ldmfd sp!, {r0-r11} + mov pc, lr + +
\ No newline at end of file diff --git a/common/wmt_display/edid.h b/common/wmt_display/edid.h new file mode 100755 index 0000000..b476a78 --- /dev/null +++ b/common/wmt_display/edid.h @@ -0,0 +1,168 @@ +/*++ + * linux/drivers/video/wmt/edid.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef EDID_H +#define EDID_H + +#define EDID_BLOCK_MAX 4 + +/*------------------------------------------------------------------------------ + Following definitions, please refer spec of EDID. You may refer it on + http://en.wikipedia.org/wiki/EDID#EDID_1.3_data_format +------------------------------------------------------------------------------*/ + +#define EDID_LENGTH 0x80 + +/*------------------------------------------------------------------------------ + Offset 00-19: HEADER INFORMATION +------------------------------------------------------------------------------*/ +/* 00¡V07: Header information "00h FFh FFh FFh FFh FFh FFh 00h" */ +#define EDID_HEADER 0x00 +#define EDID_HEADER_END 0x07 + +/* 08¡V09: Manufacturer ID. These IDs are assigned by Microsoft. + "00001=A¡¨; ¡§00010=B¡¨; ... ¡§11010=Z¡¨. Bit 7 (at address 08h) is 0, + the first character (letter) is located at bits 6 ¡÷ 2 + (at address 08h), the second character (letter) is located at + bits 1 & 0 (at address 08h) and bits 7 ¡÷ 5 (at address 09h), and the + third character (letter) is located at bits 4 ¡÷ 0 (at address 09h). +*/ +#define ID_MANUFACTURER_NAME 0x08 +#define ID_MANUFACTURER_NAME_END 0x09 + +/* 10¡V11: Product ID Code (stored as LSB first). Assigned by manufacturer */ +#define ID_MODEL 0x0a + +/* 12¡V15: 32-bit Serial Number. No requirement for the format. Usually + stored as LSB first. In order to maintain compatibility with previous + requirements the field should set at least one byte of the field to be + non-zero if an ASCII serial number descriptor is + provided in the detailed timing section. +*/ +#define ID_SERIAL_NUMBER 0x0c + +/* 16: Week of Manufacture. This varies by manufacturer. One way is to count + January 1-7 as week 1, January 8-15 as week 2 and so on. Some count + based on the week number (Sunday-Saturday). Valid range is 1-54. + 17: Year of Manufacture. Add 1990 to the value for actual year. */ +#define MANUFACTURE_WEEK 0x10 +#define MANUFACTURE_YEAR 0x11 + +/* 18: EDID Version Number. "01h" + 19: EDID Revision Number "03h" */ +#define EDID_STRUCT_VERSION 0x12 +#define EDID_STRUCT_REVISION 0x13 + +#define EDID_MAX_HOR_IMAGE_SIZE 0x15 +#define EDID_MAX_VER_IMAGE_SIZE 0x16 + +/*------------------------------------------------------------------------------ + Offset 20-24: BASIC DISPLAY PARAMETERS +------------------------------------------------------------------------------*/ +#define DPMS_FLAGS 0x18 +#define ESTABLISHED_TIMING_I 0x23 +#define ESTABLISHED_TIMING_II 0x24 +#define MANUFACTURERS_TIMINGS 0x25 + +#define STANDARD_TIMING_IDENTIFICATION_START 0x26 +#define STANDARD_TIMING_IDENTIFICATION_SIZE 16 + +#define DETAILED_TIMING_DESCRIPTIONS_START 0x36 +#define DETAILED_TIMING_DESCRIPTION_SIZE 18 +#define NO_DETAILED_TIMING_DESCRIPTIONS 4 + +#define DETAILED_TIMING_DESCRIPTION_1 0x36 +#define DETAILED_TIMING_DESCRIPTION_2 0x48 +#define DETAILED_TIMING_DESCRIPTION_3 0x5a +#define DETAILED_TIMING_DESCRIPTION_4 0x6c + +#define EDID_TMR_INTERLACE BIT(31) +#define EDID_TMR_FREQ 0xFF +struct edid_timing_t { + unsigned int resx; + unsigned int resy; + int freq; /* EDID_TMR_XXX */ +}; + +struct vic_3d_t { + char vic; + unsigned int mask; +}; + +/* EDID option flag */ +#define EDID_OPT_VALID 0x01 +#define EDID_OPT_YUV422 0x10 +#define EDID_OPT_YUV444 0x20 +#define EDID_OPT_AUDIO 0x40 +#define EDID_OPT_UNDERSCAN 0x80 +#define EDID_OPT_HDMI 0x100 +#define EDID_OPT_3D BIT(9) +#define EDID_OPT_16_9 BIT(10) + +struct edid_info_t { + unsigned int establish_timing; + struct edid_timing_t standard_timing[8]; + struct fb_videomode detail_timing[4]; + struct fb_videomode cea_timing[6]; + char cea_vic[8]; + struct vic_3d_t vic_3d[16]; + unsigned int pixel_clock_limit; + unsigned int option; + unsigned short hdmi_phy_addr; + int width; + int height; +}; + +#define VENDOR_NAME_LEN 4 +#define MONITOR_NAME_LEN 20 +#define AUD_SAD_NUM 32 +struct sad_t { + char flag; /* 0: sad available, 1: sad invalid */ + char sad_byte[3]; +}; + +struct tv_name_t{ + char vendor_name[VENDOR_NAME_LEN]; + char monitor_name[MONITOR_NAME_LEN]; +}; + +struct edid_parsed_t { + struct tv_name_t tv_name; + struct sad_t sad[AUD_SAD_NUM]; +}; + +extern struct edid_info_t edid_info; +extern int edid_msg_enable; +extern int edid_disable; +extern struct edid_parsed_t edid_parsed; + +extern int edid_parse(char *edid, struct edid_info_t *info); +extern int edid_find_support(struct edid_info_t *info, unsigned int resx, + unsigned int resy, int freq, struct fb_videomode **vmode); +extern void edid_dump(char *edid); +extern int edid_checksum(char *edid, int len); +extern unsigned int edid_get_hdmi_phy_addr(void); +extern unsigned int edid_get_hdmi_3d_mask(struct edid_info_t *info, + int vic); + +#endif diff --git a/common/wmt_display/env_parse.c b/common/wmt_display/env_parse.c new file mode 100755 index 0000000..17953b7 --- /dev/null +++ b/common/wmt_display/env_parse.c @@ -0,0 +1,398 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> + +#include "lcd.h" +#include "wmt_display.h" + +#if 0 +int parse_display_params(char *name,long *ps) +{ + enum + { + idx_vout, + idx_op1, + idx_op2, + idx_resx, + idx_resy, + idx_fps_pixclk, + idx_max + }; + + char *p; +// long ps[idx_max]; + char * endp; + int i = 0; + + p = getenv(name); + if (!p) { + printf("please set %s\n", name); + return -1; + } else + printf("display param (setting): %s\n", p); + + while (i < idx_max) { + ps[i++] = simple_strtoul(p, &endp, 10); + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + + if (i != idx_max) { + printf("display param Error: need %d arg count, but get %d\n", idx_max, i); + return -1; + } + return 0; +} +#endif + +int parse_gpio_operation(char *name) +{ + enum + { + idx_id, + idx_act, + idx_bitmap, + idx_ctl, + idx_oc, + idx_od, + idx_max + }; + + char *p; + long ps[idx_max]; + char * endp; + int i = 0; + + p = getenv(name); + if (!p) { + printf("please set %s , for lcd power control pin\n", name); + return -1; + } else + printf("lcd power control pin (setting): %s\n", p); + + while (i < idx_max) { + ps[i++] = simple_strtoul(p, &endp, 16); + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + g_lcd_pw_pin.id = ps[0]; + g_lcd_pw_pin.act = ps[1]; + g_lcd_pw_pin.bitmap = ps[2]; + g_lcd_pw_pin.ctl = ps[3]; + g_lcd_pw_pin.oc = ps[4]; + g_lcd_pw_pin.od = ps[5]; + return 0; +} + +int parse_gpio_param(const char *name, struct gpio_param_t *p_gpio_pin) +{ + enum + { + idx_flag, + idx_gpiono, + idx_act, + idx_max + }; + + char *p; + long ps[idx_max] = {0}; + char * endp; + int i = 0; + + memset(p_gpio_pin, 0, sizeof(struct gpio_param_t)); + + p = getenv(name); + if (!p) + return -1; + + //printf("parse_gpio_param: %s\n", p); + + while (i < idx_max) { + ps[i++] = simple_strtoul(p, &endp, 10); + + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + p_gpio_pin->flag = ps[0]; + p_gpio_pin->gpiono = ps[1]; + p_gpio_pin->act = ps[2]; + + return 0; +} + +#if 0 +int parse_display_tmr(char *name) +{ + enum + { + idx_pixel_clock, + idx_option, + idx_hsync, + idx_hbp, + idx_hpixel, + idx_hfp, + idx_vsync, + idx_vbp, + idx_vpixel, + idx_vfp, + idx_max + }; + + char *p; + long ps[idx_max]; + char * endp; + int i = 0; + + p = getenv(name); + if (!p) { + printf("please set %s , for timing setting\n", name); + return -1; + } else + printf("display tmr (setting): %s\n", p); + + g_display_vaild &= ~TMRFROMENV; + while (i < idx_max) { + ps[i++] = simple_strtoul(p, &endp, 10); + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + + if (i != idx_max) { + printf("display tmr Error: need %d arg count, but get %d\n", idx_max, i); + return -1; + } + + g_display_tmr.pixel_clock = ps[idx_pixel_clock]*1000; + g_display_tmr.option = ps[idx_option]; + + g_display_tmr.hsync = ps[idx_hsync]; + g_display_tmr.hbp = ps[idx_hbp]; + g_display_tmr.hpixel = ps[idx_hpixel]; + g_display_tmr.hfp = ps[idx_hfp]; + + g_display_tmr.vsync = ps[idx_vsync]; + g_display_tmr.vbp = ps[idx_vbp]; + g_display_tmr.vpixel = ps[idx_vpixel]; + g_display_tmr.vfp = ps[idx_vfp]; + + g_display_vaild |= TMRFROMENV; + + return 0; +} +#endif + +#ifdef CONFIG_VPP_SHENZHEN +int parse_backlight_params(void) +{ + enum { + idx_pwm_no, + idx_invert, + idx_gpio, /* switch */ + idx_active, + idx_max, + }; + + char *p; + long ps[idx_max] = { 0, 0, -1, 0 }; + char *endp; + int i = 0; + static char env[] = "wmt.backlight.param"; + + p = getenv(env); + if (!p) { + printf("please set %s\n", env); + return -1; + } + + while (i < idx_max) { + ps[i++] = simple_strtoul(p, &endp, 10); + + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + + memset(&g_backlight_param, 0, sizeof(g_backlight_param)); + g_backlight_param.pwm_no = ps[0]; + g_backlight_param.invert = ps[1]; + g_backlight_param.gpio = ps[2]; + g_backlight_param.active = ps[3]; + + printf("backlight: pwmno %d, invert %d, gpio %d, active %d\n", + g_backlight_param.pwm_no, g_backlight_param.invert, + g_backlight_param.gpio, g_backlight_param.active); + + return 0; +} +#endif + +/* + val is used if setting comes from command , like + #display setpwm 0:2000:75 + otherwise , we get pwm setting from env ("name") +*/ +int parse_pwm_params(char *name, char *val) +{ + //pwmparam: no,scalar,period,duty + //comment: + // no: PWM no. Range: 0 ~ 3 + // scalar: PWM scalar. Range: 1 ~ 1024 + // period: PWM period. Range: 1 ~ 4096 + // duty: PWM duty. Range: 1 ~ 4096 + // -- Note: All PWM parameters are denoted using decimal number + enum + { + idx_pwm_no, + idx_scalar, + idx_period, + idx_duty, + idx_max + }; + + long ps[idx_max]; + char * p; + char * p1; + char * endp; + int i = 0; + struct wmt_pwm_setting_t setting; + + g_display_vaild &= ~PWMDEFMASK; + g_display_vaild |= PWMDEFTP; + g_pwm_setting.pwm_no = 0; + g_pwm_setting.scalar = 0; + g_pwm_setting.period = 2000; + g_pwm_setting.duty = 75; + + if (val == NULL) { + p = getenv(name); + if (!p) { + printf("%s is not found , run PWM param (tp default) = 0:2000:75\n", name); + return 0; + } + } else + p = val; + + p1 = p; + while (i < idx_max) { + if (i == 0) + ps[i++] = simple_strtoul(p, &endp, 16); + else + ps[i++] = simple_strtoul(p, &endp, 10); + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + + memset(&setting, 0, sizeof(struct wmt_pwm_setting_t)); + setting.config = ps[idx_pwm_no]; + ps[idx_pwm_no] &= 0xf; + if (i == idx_duty) { // run as taipei define ( freq , level ) + //printf("PWM param (tp setting) : freq,level = %s\n", p1); + if(ps[idx_pwm_no] >= 0 && ps[idx_pwm_no] <= 3) + setting.pwm_no = ps[idx_pwm_no]; + else { + printf("PWM param Error: no = %d, it's range should be 0 ~3\n", ps[idx_pwm_no]); + printf("PWM param (tp default) = 0:2000:750\n"); + return 0; + } + if (ps[idx_scalar] != 0) + setting.period = ps[idx_scalar]; + else { + printf("PWM param error : freq = 0\n"); + printf("PWM param (tp default) = 0:2000:75\n"); + return 0; + } + setting.duty = ps[idx_period]; + } else if (i == idx_max) { + //printf("PWM param (sz setting) : scalar,period,duty = %s\n", p1); + g_display_vaild &= ~PWMDEFMASK; + g_display_vaild |= PWMDEFSZ; + g_pwm_setting.pwm_no = 0; + g_pwm_setting.scalar = 319; + g_pwm_setting.period = 1000; + g_pwm_setting.duty = 750; + + if(ps[idx_pwm_no] >= 0 && ps[idx_pwm_no] <= 3) + setting.pwm_no = ps[idx_pwm_no]; + else { + printf("PWM param Error: no = %d, it's range should be 0 ~3\n", ps[idx_pwm_no]); + printf("So use defualt PWM param = 0:319:1000:750\n"); + return 0; + } + + if (ps[idx_scalar] > 0 && ps[idx_scalar] <= 1024) + setting.scalar = ps[idx_scalar]; + else { + printf("PWM param Error: scalar = %d, it's range should be 1 ~ 1024\n", ps[idx_scalar]); + printf("So use defualt PWM param = 0:319:1000:750\n"); + return 0; + } + + if (ps[idx_period] > 0 && ps[idx_period] < 4096) + setting.period = ps[idx_period]; + else { + printf("PWM param Error: period = %d, it's range should be 1 ~ 4096\n", ps[idx_period]); + printf("So use defualt PWM param = 0:319:1000:750\n"); + return 0; + } + + if (ps[idx_duty] > 0 && ps[idx_duty] < 4096) + setting.duty = ps[idx_duty]; + else { + printf("PWM param Error: duty = %d, it's range should be 0 ~ 4096\n", ps[idx_duty]); + printf("So use defualt PWM param = 0:319:1000:750\n"); + return 0; + } + } else { + printf("PWM param Error: need %d arg count, but get %d\n", idx_max, i); + printf("PWM param (default) = 0:2000:75 \n"); + return 0; + } + memcpy(&g_pwm_setting, &setting, sizeof(struct wmt_pwm_setting_t)); + return 0; +} diff --git a/common/wmt_display/govrh.c b/common/wmt_display/govrh.c new file mode 100755 index 0000000..214cab6 --- /dev/null +++ b/common/wmt_display/govrh.c @@ -0,0 +1,1932 @@ +/*++ + * linux/drivers/video/wmt/govrh.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define GOVRH_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ + +#include "govrh.h" + +#ifdef WMT_FTBLK_GOVRH +void govrh_reg_dump(struct vpp_mod_base_t *base) +{ + struct govrh_mod_t *p_govr = (struct govrh_mod_t *) base; + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + int igs_mode[4] = {888, 555, 666, 565}; + + DPRINT("========== GOVRH register dump ==========\n"); + vpp_reg_dump((unsigned int)base->mmio, 512); + DPRINT("=========================================\n"); + DPRINT("MIF enable %d\n", regs->mif.b.enable); + DPRINT("color bar enable %d,mode %d,inv %d\n", + regs->cb_enable.b.enable, regs->cb_enable.b.mode, + regs->cb_enable.b.inversion); + DPRINT("---------- frame buffer ----------\n"); + DPRINT("colr format %s\n", + vpp_colfmt_str[govrh_get_color_format(p_govr)]); + DPRINT("width active %d,fb %d\n", regs->pixwid, regs->bufwid); + DPRINT("Y addr 0x%x, C addr 0x%x\n", regs->ysa, regs->csa); + DPRINT("Y addr2 0x%x, C addr2 0x%x\n", regs->ysa2, regs->csa2); + DPRINT("H crop %d, V crop %d\n", regs->hcrop, regs->vcrop); + DPRINT("source format %s,H264 %d\n", + (regs->srcfmt) ? "field" : "frame", regs->h264_input_en); + DPRINT("H scaleup %d,dirpath %d\n", regs->hscale_up, regs->dirpath); + DPRINT("---------- GOVRH TG1 ----------\n"); + DPRINT("TG enable %d, Twin mode %d\n", + regs->tg_enable.b.enable, regs->tg_enable.b.mode); + DPRINT("DVO clk %d,%d,Read cyc %d\n", + vpp_get_base_clock(p_govr->mod), + auto_pll_divisor((p_govr->mod == VPP_MOD_GOVRH) ? + DEV_HDMILVDS : DEV_DVO, GET_FREQ, 0, 0), + regs->read_cyc); + DPRINT("H total %d, Sync %d, beg %d, end %d\n", + regs->h_allpxl, regs->hdmi_hsynw, + regs->actpx_bg, regs->actpx_end); + DPRINT("V total %d, Sync %d, beg %d, end %d\n", + regs->v_allln, regs->hdmi_vbisw, + regs->actln_bg, regs->actln_end); + DPRINT("VBIE %d,PVBI %d\n", regs->vbie_line, regs->pvbi_line); + DPRINT("---------- GOVRH TG2 ----------\n"); + DPRINT("H total %d, Sync %d, beg %d, end %d\n", + regs->h_allpxl2, regs->hdmi_hsynw2, + regs->actpx_bg2, regs->actpx_end2); + DPRINT("V total %d, Sync %d, beg %d, end %d\n", + regs->v_allln2, regs->hdmi_vbisw2, + regs->actln_bg2, regs->actln_end2); + DPRINT("VBIE %d,PVBI %d\n", regs->vbie_line2, regs->pvbi_line2); + DPRINT("---------- DVO ----------------\n"); + DPRINT("DVO enable %d,data width %d bits\n", + regs->dvo_set.b.enable, (regs->dvo_set.b.outwidth) ? 12 : 24); + DPRINT("DVO color format %s\n", + vpp_colfmt_str[govrh_get_dvo_color_format(p_govr)]); + DPRINT("Polar H %s,V %s\n", + (regs->dvo_set.b.hsync_polar) ? "Low" : "High", + (regs->dvo_set.b.vsync_polar) ? "Low" : "High"); + DPRINT("DVO RGB mode %d,%s\n", igs_mode[regs->igs_mode.b.mode], + (regs->igs_mode.b.ldi) ? "msb" : "lsb"); + DPRINT("RGB swap %d\n", regs->dvo_set.b.rgb_swap); + DPRINT("---------- CSC ----------------\n"); + DPRINT("CSC mode %s\n", + (regs->csc_mode.b.mode) ? "YUV2RGB" : "RGB2YUV"); + DPRINT("CSC enable DVO %d,DISP %d,LVDS %d,HDMI %d\n", + regs->yuv2rgb.b.dvo, regs->yuv2rgb.b.disp, + regs->yuv2rgb.b.lvds, regs->yuv2rgb.b.hdmi); + DPRINT("---------- Misc ----------------\n"); + DPRINT("Contrast 0x%x,Brightness 0x%x\n", + regs->contrast.val, regs->brightness); + DPRINT("LVDS RGB mode %d,%s\n", igs_mode[regs->igs_mode2.b.mode], + (regs->igs_mode2.b.ldi) ? "msb" : "lsb"); + DPRINT("HDMI 3D mode %d,blank 0x%x\n", + regs->hdmi_3d.b.mode, regs->hdmi_3d.b.blank_value); +#ifdef WMT_FTBLK_GOVRH_CURSOR + DPRINT("---------- CURSOR -------------\n"); + DPRINT("enable %d,field %d\n", + regs->cur_status.b.enable, regs->cur_status.b.out_field); + DPRINT("width %d,fb width %d\n", regs->cur_width, regs->cur_fb_width); + DPRINT("crop(%d,%d)\n", regs->cur_hcrop, regs->cur_vcrop); + DPRINT("coord H(%d,%d),V(%d,%d)\n", + regs->cur_hcoord.b.start, regs->cur_hcoord.b.end, + regs->cur_vcoord.b.start, regs->cur_vcoord.b.end); + DPRINT("color key enable 0x%x,color key 0x%x,alpha enable %d\n", + regs->cur_color_key.b.enable, regs->cur_color_key.b.colkey, + regs->cur_color_key.b.alpha); +#endif +} + + +void govrh_set_tg_enable(struct govrh_mod_t *base, vpp_flag_t enable) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, enable); + + regs->tg_enable.b.enable = enable; +} + +unsigned int govrh_set_clock(struct govrh_mod_t *base, + unsigned int pixel_clock) +{ + int pmc_clk = 0; + + DBG_MSG("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, pixel_clock); + + base->vo_clock = pixel_clock; + if (base->mod == VPP_MOD_GOVRH) { + pmc_clk = auto_pll_divisor(DEV_HDMILVDS, SET_PLLDIV, + 0, pixel_clock); + DBG_MSG("set %d,get %d\n", pixel_clock, + auto_pll_divisor(DEV_HDMILVDS, GET_FREQ, 0, 0)); + g_vpp.hdmi_pixel_clock = pmc_clk; + } else + pmc_clk = auto_pll_divisor(DEV_DVO, SET_PLLDIV, 0, pixel_clock); + return 0; +} + +void govrh_set_tg1(struct govrh_mod_t *base, vpp_clock_t *timing) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + regs->tg_enable.b.mode = 0; + regs->dstfmt = 0; + regs->read_cyc = timing->read_cycle; + + regs->actpx_bg = timing->begin_pixel_of_active; + regs->actpx_end = timing->end_pixel_of_active; + regs->h_allpxl = timing->total_pixel_of_line; + + regs->actln_bg = timing->begin_line_of_active + 1; + regs->actln_end = timing->end_line_of_active + 1; + regs->v_allln = timing->total_line_of_frame; + + regs->vbie_line = timing->line_number_between_VBIS_VBIE; + /* pre vbi should more 6 to avoid garbage line */ + regs->pvbi_line = (timing->line_number_between_PVBI_VBIS < 6) ? + 6 : timing->line_number_between_PVBI_VBIS; + + regs->hdmi_hsynw = timing->hsync; + regs->hdmi_vbisw = timing->vsync; + +#ifdef DEBUG_DETAIL + vpp_show_timing("govrh tg1", 0, timing); +#endif +} + +int govrh_get_tg_mode(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + return regs->tg_enable.b.mode; +} + +void govrh_set_tg2(struct govrh_mod_t *base, vpp_clock_t *timing) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + regs->tg_enable.b.mode = 1; + regs->dstfmt = 1; + + regs->actpx_bg2 = timing->begin_pixel_of_active; + regs->actpx_end2 = timing->end_pixel_of_active; + regs->h_allpxl2 = timing->total_pixel_of_line; + + regs->actln_bg2 = timing->begin_line_of_active + 1; + regs->actln_end2 = timing->end_line_of_active + 1; + regs->v_allln2 = timing->total_line_of_frame; + + regs->vbie_line2 = timing->line_number_between_VBIS_VBIE; + regs->pvbi_line2 = (timing->line_number_between_PVBI_VBIS < 6) ? + 6 : timing->line_number_between_PVBI_VBIS; + + regs->hdmi_hsynw2 = timing->hsync; + regs->hdmi_vbisw2 = timing->vsync; + +#ifdef DEBUG_DETAIL + vpp_show_timing("govrh tg2", 0, timing); +#endif +} + +void govrh_get_tg(struct govrh_mod_t *base, vpp_clock_t *tmr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + tmr->read_cycle = regs->read_cyc; + tmr->total_pixel_of_line = regs->h_allpxl; + tmr->begin_pixel_of_active = regs->actpx_bg; + tmr->end_pixel_of_active = regs->actpx_end; + + tmr->total_line_of_frame = regs->v_allln; + tmr->begin_line_of_active = (regs->actln_bg - 1); + tmr->end_line_of_active = (regs->actln_end - 1); + + tmr->line_number_between_VBIS_VBIE = regs->vbie_line; + tmr->line_number_between_PVBI_VBIS = regs->pvbi_line; + + tmr->hsync = regs->hdmi_hsynw; + tmr->vsync = regs->hdmi_vbisw; + + if (regs->tg_enable.b.mode) { + tmr->vsync = (tmr->vsync - 1) * 2; + tmr->begin_line_of_active = (tmr->begin_line_of_active - 1) * 2; + tmr->end_line_of_active = (tmr->end_line_of_active - 1) * 2; + tmr->total_line_of_frame = (tmr->total_line_of_frame - 1) * 2; + } +} + +int govrh_get_hscale_up(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + int reg; + + reg = regs->hscale_up & 0x1; + DBG_DETAIL("(govr %d,reg %d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, reg); + return reg; +} + +void govrh_set_direct_path(struct govrh_mod_t *base, int enable) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, enable); + + regs->dirpath = enable; +} + +enum vpp_int_err_t govrh_get_int_status(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + enum vpp_int_err_t int_sts; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + int_sts = 0; + if (regs->interrupt.b.err_sts) + int_sts |= VPP_INT_ERR_GOVRH_MIF; + return int_sts; +} + +void govrh_clean_int_status(struct govrh_mod_t *base, + enum vpp_int_err_t int_sts) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + unsigned int val; + + DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, int_sts); + + if (int_sts & VPP_INT_ERR_GOVRH_MIF) { + val = regs->interrupt.val; + val = (val & 0xff) + 0x20000; + regs->interrupt.val = val; + } +} + +void govrh_set_int_enable(struct govrh_mod_t *base, + vpp_flag_t enable, enum vpp_int_err_t int_bit) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, enable); + + /* clean status first before enable/disable interrupt */ + govrh_clean_int_status(base, int_bit); + + if (int_bit & VPP_INT_ERR_GOVRH_MIF) + regs->interrupt.b.mem_enable = enable; +} + +int govrh_get_dvo_enable(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + return regs->dvo_set.b.enable; +} + +void govrh_set_dvo_enable(struct govrh_mod_t *base, vpp_flag_t enable) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; +/* DPRINT("[GOVRH] %s(%d)\n",__FUNCTION__,enable); */ + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable); + + regs->dvo_set.b.enable = enable; + if (enable) { + /* GPIO to function pin */ + outl(0x0, GPIO_BASE_ADDR + 0x44); + /* GPIO pull disable */ + outl(0x0, GPIO_BASE_ADDR + 0x484); + /* 1:pullup,0:pulldn */ + outl(0x0, GPIO_BASE_ADDR + 0x4C4); + return; + } + /* disable dvo */ + outl(0xFFFFFFFF, GPIO_BASE_ADDR + 0x44); /* Enable GPIO */ + outl(0x0, GPIO_BASE_ADDR + 0x84); /* GPIO output enable */ + outl(0x0, GPIO_BASE_ADDR + 0x484); /* GPIO pull disable */ + outl(0x0, GPIO_BASE_ADDR + 0x4C4); /* 1:pullup,0:pulldn */ +} + +void govrh_set_dvo_sync_polar(struct govrh_mod_t *base, + vpp_flag_t hsync, vpp_flag_t vsync) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, hsync, vsync); + + regs->dvo_set.b.hsync_polar = hsync; + regs->dvo_set.b.vsync_polar = vsync; +} + +vdo_color_fmt govrh_get_dvo_color_format(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + if (regs->dvo_pix.b.rgb) + return VDO_COL_FMT_ARGB; + if (regs->dvo_pix.b.yuv422) + return VDO_COL_FMT_YUV422H; + return VDO_COL_FMT_YUV444; +} + +void govrh_set_dvo_color_format(struct govrh_mod_t *base, + vdo_color_fmt fmt) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%s)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, vpp_colfmt_str[fmt]); + + switch (fmt) { + case VDO_COL_FMT_ARGB: + regs->dvo_pix.b.rgb = 1; + regs->dvo_pix.b.yuv422 = 0; + break; + case VDO_COL_FMT_YUV422H: + regs->dvo_pix.b.rgb = 0; + regs->dvo_pix.b.yuv422 = 1; + break; + case VDO_COL_FMT_YUV444: + default: + regs->dvo_pix.b.rgb = 0; + regs->dvo_pix.b.yuv422 = 0; + break; + } +} + +void govrh_set_dvo_outdatw(struct govrh_mod_t *base, + vpp_datawidht_t width) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + unsigned int clk_delay; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, width); + + regs->dvo_set.b.outwidth = (width == VPP_DATAWIDHT_12) ? 1 : 0; + + clk_delay = (width == VPP_DATAWIDHT_24) ? + VPP_GOVR_DVO_DELAY_24 : VPP_GOVR_DVO_DELAY_12; + govrh_set_dvo_clock_delay(base, ((clk_delay & BIT14) != 0x0), + clk_delay & 0x3FFF); +} + +void govrh_set_dvo_clock_delay(struct govrh_mod_t *base, + int inverse, int delay) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? + 1 : 2, inverse, delay); + +#ifdef CONFIG_HW_DVO_DELAY + regs = p_govrh->mmio; +#endif + + regs->dvo_dly_sel.b.inv = inverse; + regs->dvo_dly_sel.b.delay = delay; +} + +void govrh_set_colorbar(struct govrh_mod_t *base, + vpp_flag_t enable, int mode, int inv) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable); + + regs->cb_enable.b.enable = enable; + regs->cb_enable.b.mode = mode; + regs->cb_enable.b.inversion = inv; +} + +void govrh_set_contrast(struct govrh_mod_t *base, unsigned int value) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,0x%x)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, value); + + regs->contrast.val = value; +} + +unsigned int govrh_get_contrast(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + return regs->contrast.val; +} + +void govrh_set_brightness(struct govrh_mod_t *base, unsigned int value) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,0x%x)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, value); + + regs->brightness = value; +} + +unsigned int govrh_get_brightness(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + return regs->brightness; +} + +void govrh_set_saturation(struct govrh_mod_t *base, unsigned int value) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,0x%x)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, value); + + regs->saturation.val = value; + regs->saturation_enable.b.enable = 1; +} + +unsigned int govrh_get_saturation(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + return regs->saturation.val; +} + +void govrh_set_MIF_enable(struct govrh_mod_t *base, vpp_flag_t enable) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable); + + regs->mif.b.enable = enable; +} + +int govrh_get_MIF_enable(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + return regs->mif.b.enable; +} + +void govrh_set_frame_mode(struct govrh_mod_t *base, + unsigned int width, vdo_color_fmt colfmt) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + int y_byte, c_byte; + int enable; + + enable = 1; + vpp_get_colfmt_bpp(colfmt, &y_byte, &c_byte); + y_byte = width * y_byte / 8; + if (y_byte % 8) + enable = 0; + if (c_byte) { + c_byte = width * c_byte / 8; + if (c_byte % 8) + enable = 0; + } + if (regs->bufwid % 128) + enable = 0; + if (width == 720) + enable = 0; + regs->mif_frame_mode.b.frame_enable = enable; + regs->mif_frame_mode.b.req_num = + (y_byte / 128) + ((y_byte % 128) ? 1 : 0); + regs->mif_frame_mode.b.req_num_c = + (c_byte) ? ((c_byte / 128) + ((c_byte % 128) ? 1 : 0)) : 0; +} + +void govrh_set_color_format(struct govrh_mod_t *base, + vdo_color_fmt format) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%s)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, vpp_colfmt_str[format]); + + if (format < VDO_COL_FMT_ARGB) + regs->yuv2rgb.b.rgb_mode = 0; + + switch (format) { + case VDO_COL_FMT_YUV420: + regs->colfmt = 1; + regs->colfmt2 = 0; + break; + case VDO_COL_FMT_YUV422H: + regs->colfmt = 0; + regs->colfmt2 = 0; + break; + case VDO_COL_FMT_YUV444: + regs->colfmt = 0; + regs->colfmt2 = 1; + break; + case VDO_COL_FMT_ARGB: + regs->yuv2rgb.b.rgb_mode = 1; + break; + case VDO_COL_FMT_RGB_1555: + regs->yuv2rgb.b.rgb_mode = 2; + break; + case VDO_COL_FMT_RGB_565: + regs->yuv2rgb.b.rgb_mode = 3; + break; + default: + DBGMSG("*E* check the parameter\n"); + return; + } +#ifdef WMT_FTBLK_GOVRH_CURSOR + govrh_CUR_set_colfmt((struct govrh_cursor_mod_t *)p_cursor, format); +#endif + govrh_set_frame_mode(base, regs->pixwid, format); + regs->saturation_enable.b.format = (regs->yuv2rgb.b.rgb_mode) ? 1 : 0; +} + +vdo_color_fmt govrh_get_color_format(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + switch (regs->yuv2rgb.b.rgb_mode) { + case 1: + return VDO_COL_FMT_ARGB; + case 2: + return VDO_COL_FMT_RGB_1555; + case 3: + return VDO_COL_FMT_RGB_565; + default: + break; + } + if (regs->colfmt2) + return VDO_COL_FMT_YUV444; + if (regs->colfmt) + return VDO_COL_FMT_YUV420; + return VDO_COL_FMT_YUV422H; +} + +void govrh_set_source_format(struct govrh_mod_t *base, + vpp_display_format_t format) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, format); + + regs->srcfmt = (format == VPP_DISP_FMT_FIELD) ? 1 : 0; +} + +void govrh_set_output_format(struct govrh_mod_t *base, + vpp_display_format_t field) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, field); + + regs->dstfmt = (field == VPP_DISP_FMT_FIELD) ? 1 : 0; +} + +void govrh_set_fb_addr(struct govrh_mod_t *base, + unsigned int y_addr, unsigned int c_addr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + /* DBG_DETAIL("(govr %d,0x%x,0x%x)\n", + (base->mod == VPP_MOD_GOVRH)? 1:2,y_addr,c_addr); */ +#ifdef DEBUG + if ((y_addr % GOVRH_FRAMEBUF_ALIGN) || (c_addr % GOVRH_FRAMEBUF_ALIGN)) + DBG_ERR("addr should align %d(0x%x,0x%x)\n", + GOVRH_FRAMEBUF_ALIGN, y_addr, c_addr); +#endif + regs->ysa = y_addr; + regs->csa = c_addr; +} + +void govrh_get_fb_addr(struct govrh_mod_t *base, + unsigned int *y_addr, unsigned int *c_addr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + *y_addr = regs->ysa; + *c_addr = regs->csa; + + DBG_DETAIL("(govr %d,0x%x,0x%x)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, *y_addr, *c_addr); +} + +void govrh_set_fb2_addr(struct govrh_mod_t *base, + unsigned int y_addr, unsigned int c_addr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,0x%x,0x%x)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, y_addr, c_addr); +#ifdef DEBUG + if ((y_addr % GOVRH_FRAMEBUF_ALIGN) || (c_addr % GOVRH_FRAMEBUF_ALIGN)) + DBG_ERR("addr should align %d(0x%x,0x%x)\n", + GOVRH_FRAMEBUF_ALIGN, y_addr, c_addr); +#endif + regs->ysa2 = y_addr; + regs->csa2 = c_addr; +} + +void govrh_get_fb2_addr(struct govrh_mod_t *base, + unsigned int *y_addr, unsigned int *c_addr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + *y_addr = regs->ysa2; + *c_addr = regs->csa2; + + DBG_DETAIL("(govr %d,0x%x,0x%x)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, *y_addr, *c_addr); +} + +void govrh_set_fb_width(struct govrh_mod_t *base, unsigned int width) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, width); + + regs->bufwid = width; +} + +#define GOVRH_CURSOR_RIGHT_POS 6 +void govrh_set_fb_info(struct govrh_mod_t *base, unsigned int width, + unsigned int act_width, unsigned int x_offset, unsigned int y_offset) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,fb_w %d,img_w %d,x %d,y %d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, + width, act_width, x_offset, y_offset); + + regs->pixwid = act_width; + regs->bufwid = width; + regs->hcrop = x_offset; + regs->vcrop = y_offset; + govrh_set_frame_mode(base, act_width, govrh_get_color_format(base)); + +#ifdef WMT_FTBLK_GOVRH_CURSOR + /* cursor postion over when change resolution */ + if ((regs->actpx_end - regs->actpx_bg) != regs->pixwid) { + if (regs->cur_hcoord.b.end >= + (regs->pixwid - GOVRH_CURSOR_RIGHT_POS)) { + int pos; + + pos = regs->pixwid - GOVRH_CURSOR_RIGHT_POS; + regs->cur_hcoord.b.end = pos; + pos -= regs->cur_width; + regs->cur_hcoord.b.start = (pos+1); + + p_cursor->posx = pos; + } + } +#endif +} + +void govrh_get_fb_info(struct govrh_mod_t *base, unsigned int *width, + unsigned int *act_width, unsigned int *x_offset, unsigned int *y_offset) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + *act_width = regs->pixwid; + *width = regs->bufwid; + *x_offset = regs->hcrop; + *y_offset = regs->vcrop; +} + +void govrh_set_fifo_index(struct govrh_mod_t *base, unsigned int index) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, index); + + regs->fhi = index; +} + +void govrh_set_reg_level(struct govrh_mod_t *base, vpp_reglevel_t level) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, level); + + regs->sts.b.level = (level == VPP_REG_LEVEL_1) ? 0 : 1; +} + +void govrh_set_reg_update(struct govrh_mod_t *base, vpp_flag_t enable) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable); + + regs->sts.b.update = enable; +} + +void govrh_set_tg(struct govrh_mod_t *base, + vpp_clock_t *tmr, unsigned int pixel_clock) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + int tg_enable; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, pixel_clock); + + tg_enable = regs->tg_enable.b.enable; + regs->tg_enable.b.enable = 0; + + tmr->read_cycle = govrh_set_clock(base, pixel_clock); + govrh_set_tg1(base, tmr); + + regs->tg_enable.b.enable = tg_enable; +} + +void govrh_set_csc_mode(struct govrh_mod_t *base, vpp_csc_t mode) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + vdo_color_fmt src_fmt, dst_fmt; + unsigned int enable; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, mode); + + enable = 0; + src_fmt = (govrh_get_color_format(base) < VDO_COL_FMT_ARGB) ? + VDO_COL_FMT_YUV444 : VDO_COL_FMT_ARGB; + dst_fmt = (govrh_get_dvo_color_format(base) < VDO_COL_FMT_ARGB) ? + VDO_COL_FMT_YUV444 : VDO_COL_FMT_ARGB; + if (src_fmt == VDO_COL_FMT_ARGB) + enable |= (dst_fmt != VDO_COL_FMT_ARGB) ? BIT0 : 0x00; /* DVO */ + else + enable |= (dst_fmt == VDO_COL_FMT_ARGB) ? BIT0 : 0x00; /* DVO */ +#ifdef WMT_FTBLK_LVDS + vpp_set_clock_enable(DEV_LVDS, 1, 0); + if (src_fmt == VDO_COL_FMT_ARGB) { + if (lvds_get_colfmt() < VDO_COL_FMT_ARGB) + enable |= BIT3; + } else { + if (lvds_get_colfmt() >= VDO_COL_FMT_ARGB) + enable |= BIT3; + } + vpp_set_clock_enable(DEV_LVDS, 0, 0); +#endif +#ifdef WMT_FTBLK_HDMI + vpp_set_clock_enable(DEV_HDMI, 1, 0); + if (src_fmt == VDO_COL_FMT_ARGB) { + if (hdmi_get_output_colfmt() < VDO_COL_FMT_ARGB) + enable |= BIT4; + } else { + if (hdmi_get_output_colfmt() >= VDO_COL_FMT_ARGB) + enable |= BIT4; + } + vpp_set_clock_enable(DEV_HDMI, 0, 0); +#endif + mode = vpp_check_csc_mode(mode, src_fmt, dst_fmt, enable); + if (mode >= VPP_CSC_MAX) { + enable = 0; + /* for internal color bar (YUV base) */ + mode = base->fb_p->csc_mode; + } + + mode = (base->csc_mode_force) ? base->csc_mode_force : mode; + + regs->dmacsc_coef0 = vpp_csc_parm[mode][0]; /* C1,C2 */ + regs->dmacsc_coef1 = vpp_csc_parm[mode][1]; /* C3,C4 */ + regs->dmacsc_coef2 = vpp_csc_parm[mode][2]; /* C5,C6 */ + regs->dmacsc_coef3 = vpp_csc_parm[mode][3]; /* C7,C8 */ + regs->dmacsc_coef4 = vpp_csc_parm[mode][4] & 0xFFFF; /* C9 */ + regs->dmacsc_coef5 = ((vpp_csc_parm[mode][4] & 0xFFFF0000) >> 16) + + ((vpp_csc_parm[mode][5] & 0xFFFF) << 16); /* I,J */ + regs->dmacsc_coef6 = (vpp_csc_parm[mode][5] & 0xFFFF0000) >> 16; /* K */ + regs->csc_mode.val = (vpp_csc_parm[mode][6] & BIT0) + + ((vpp_csc_parm[mode][6] & BIT8) ? BIT1 : 0x0); + + /* enable bit0:DVO, bit1:VGA, bit2:DISP, bit3:LVDS, bit4:HDMI */ + regs->yuv2rgb.b.blank_zero = 1; + regs->yuv2rgb.b.dac_clkinv = 1; + regs->yuv2rgb.b.reserved1 = + (mode >= VPP_CSC_RGB2YUV_SDTV_0_255) ? 1 : 0; + regs->yuv2rgb.b.dvo = (enable & BIT0) ? 1 : 0; +#ifdef WMT_FTBLK_LVDS + regs->yuv2rgb.b.lvds = (enable & BIT3) ? 1 : 0; +#endif +#ifdef WMT_FTBLK_HDMI + regs->yuv2rgb.b.hdmi = (enable & BIT4) ? 1 : 0; +#endif +} + +void govrh_set_media_format(struct govrh_mod_t *base, vpp_flag_t h264) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, h264); + + regs->mif.b.h264 = h264; +} + +void govrh_HDMI_set_blank_value(struct govrh_mod_t *base, + unsigned int val) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2, val); + + regs->hdmi_3d.b.blank_value = val; +} + +void govrh_HDMI_set_3D_mode(struct govrh_mod_t *base, int mode) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, mode); + + /* 0-disable,3-frame pack progress(use fb1&2),7-frame pack interlace */ + regs->hdmi_3d.b.mode = mode; +} + +int govrh_is_top_field(struct govrh_mod_t *base) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + return (regs->field_status) ? 1 : 0; +} + +/*----------------------- GOVRH IGS --------------------------------------*/ +void govrh_IGS_set_mode(struct govrh_mod_t *base, + int no, int mode_18bit, int msb) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2, no); + + if (no == 0) { /* DVO */ + /* 0-24bit,10-18bit,01-555,11-565 */ + regs->igs_mode.b.mode = mode_18bit; + regs->igs_mode.b.ldi = msb; /* 0-lsb,1-msb */ + } else { /* LVDS */ + /* 0-24bit,10-18bit,01-555,11-565 */ + regs->igs_mode2.b.mode = mode_18bit; + regs->igs_mode2.b.ldi = msb; /* 0-lsb,1-msb */ + } +} + +void govrh_IGS_set_RGB_swap(struct govrh_mod_t *base, int mode) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + DBG_DETAIL("(govr %d,%d)\n", + (base->mod == VPP_MOD_GOVRH) ? 1 : 2, mode); + + /* 0-RGB [7-0], 1-RGB [0-7], 2-BGR [7-0], 3-BGR [0-7] */ + regs->dvo_set.b.rgb_swap = mode; +} + +/*----------------------- GOVRH CURSOR --------------------------------------*/ +#ifdef WMT_FTBLK_GOVRH_CURSOR +#define CONFIG_GOVR2_CURSOR +void *govrh_CUR_get_mmio(struct govrh_cursor_mod_t *base) +{ +#ifdef CONFIG_GOVR2_CURSOR + base = (struct govrh_cursor_mod_t *) + ((govrh_get_MIF_enable(p_govrh)) ? p_govrh : p_govrh2); +#endif + return base->mmio; +} + +void govrh_CUR_set_enable(struct govrh_cursor_mod_t *base, + vpp_flag_t enable) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + DBG_DETAIL("(0x%x,%d)\n", base->mmio, enable); + + regs->cur_status.b.enable = enable; +} + +void govrh_CUR_set_fb_addr(struct govrh_cursor_mod_t *base, + unsigned int y_addr, unsigned int c_addr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + DBG_DETAIL("(0x%x,0x%x,0x%x)\n", base->mmio, y_addr, c_addr); + + regs->cur_addr = y_addr; +} + +void govrh_CUR_get_fb_addr(struct govrh_cursor_mod_t *base, + unsigned int *y_addr, unsigned int *c_addr) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + *y_addr = regs->cur_addr; + *c_addr = 0; + + DBG_DETAIL("(0x%x,0x%x,0x%x)\n", base->mmio, *y_addr, *c_addr); +} + +void govrh_CUR_set_coordinate(struct govrh_cursor_mod_t *base, + unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + DBG_DETAIL("(0x%x)\n", base->mmio); + + regs->cur_hcoord.b.start = x1; + regs->cur_hcoord.b.end = x2; + regs->cur_vcoord.b.start = y1; + regs->cur_vcoord.b.end = y2; +} + +void govrh_CUR_set_position(struct govrh_cursor_mod_t *base, + unsigned int x, unsigned int y) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + unsigned int w, h; + + DBG_DETAIL("(0x%x,%d,%d)\n", base->mmio, x, y); + +/* w = regs->cur_hcoord.b.end - regs->cur_hcoord.b.start; */ + w = regs->cur_width - 1; + h = regs->cur_vcoord.b.end - regs->cur_vcoord.b.start; + govrh_CUR_set_coordinate(base, x, y, x+w, y+h); +} + +void govrh_CUR_set_color_key_mode(struct govrh_cursor_mod_t *base, + int enable, int alpha, int mode) +{ + /* + if( colkey_en ) + colkey_hit = (mode)? (data == colkey):(data != colkey); + + if( (alpha_en) or (colkey_hit) or (alpha value) ) + show pixel + */ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + DBG_DETAIL("(0x%x,%d,%d,%d)\n", base->mmio, enable, alpha, mode); + + regs->cur_color_key.b.alpha = alpha; + regs->cur_color_key.b.enable = enable; + regs->cur_color_key.b.invert = mode; +} + +void govrh_CUR_set_color_key(struct govrh_cursor_mod_t *base, + int enable, int alpha, unsigned int colkey) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + DBG_DETAIL("(0x%x,0x%x)\n", base->mmio, colkey); + + regs->cur_color_key.b.colkey = colkey; + regs->cur_color_key.b.alpha = 0; + regs->cur_color_key.b.enable = 0; + +#ifdef __KERNEL__ + if (!(alpha) && enable) { + int i, j; + unsigned int *ptr1, *ptr2; + int yuv2rgb; + + ptr1 = (unsigned int *)mb_phys_to_virt(regs->cur_addr); + for (i = 0; i < base->fb_p->fb.fb_h; i++) { + for (j = 0; j < base->fb_p->fb.fb_w; j++) { + if ((*ptr1 & 0xFFFFFF) == (colkey & 0xFFFFFF)) + *ptr1 &= 0xFFFFFF; + else + *ptr1 |= 0xFF000000; + ptr1++; + } + } + + yuv2rgb = (base->colfmt < VDO_COL_FMT_ARGB) ? 1 : 0; + ptr1 = (unsigned int *) mb_phys_to_virt(base->cursor_addr1); + ptr2 = (unsigned int *) mb_phys_to_virt(base->cursor_addr2); + for (i = 0; i < base->fb_p->fb.fb_h; i++) { + for (j = 0; j < base->fb_p->fb.fb_w; j++) { + *ptr2 = vpp_convert_colfmt(yuv2rgb, *ptr1); + ptr1++; + ptr2++; + } + } + } +#endif +} + +void govrh_CUR_set_colfmt(struct govrh_cursor_mod_t *base, + vdo_color_fmt colfmt) +{ +#ifdef __KERNEL__ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); +#endif + + DBG_DETAIL("(0x%x,%s)\n", base->mmio, vpp_colfmt_str[colfmt]); + + colfmt = (colfmt < VDO_COL_FMT_ARGB) ? + VDO_COL_FMT_YUV444 : VDO_COL_FMT_ARGB; + if (base->fb_p->fb.col_fmt == colfmt) + return; + + base->fb_p->fb.col_fmt = colfmt; +#ifdef __KERNEL__ + regs->cur_addr = (base->colfmt == colfmt) ? + base->cursor_addr1 : base->cursor_addr2; +#endif + DBG_DETAIL("(0x%x)\n", regs->cur_addr); +} + +int govrh_irqproc_set_position(void *arg) +{ + struct govrh_cursor_mod_t *base = (struct govrh_cursor_mod_t *) arg; + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + int begin; + int pos_x, pos_y; + int crop_x, crop_y; + int width, height; + int govrh_w, govrh_h; + + govrh_w = regs->actpx_end - regs->actpx_bg; + govrh_h = regs->actln_end - regs->actln_bg; + if (regs->tg_enable.b.mode) + govrh_h *= 2; + + /* cursor H */ + width = base->fb_p->fb.img_w; + begin = base->posx - base->hotspot_x; + if (begin < 0) { /* over left edge */ + pos_x = 0; + crop_x = 0 - begin; + width = width - crop_x; + } else { + pos_x = begin; + crop_x = 0; + } + if ((begin + base->fb_p->fb.img_w) > govrh_w) /* over right edge */ + width = govrh_w - begin; + +/* DPRINT("[CURSOR] H pos %d,hotspot %d,posx %d,crop %d,width %d\n", + p_cursor->posx,p_cursor->hotspot_x,pos_x,crop_x,width); */ + + /* cursor V */ + height = base->fb_p->fb.img_h; + begin = base->posy - base->hotspot_y; + if (begin < 0) { /* over top edge */ + pos_y = 0; + crop_y = 0 - begin; + height = height - crop_y; + } else { + pos_y = begin; + crop_y = 0; + } + if ((begin + base->fb_p->fb.img_h) > govrh_h) /* over right edge */ + height = govrh_h - begin; + + if (regs->tg_enable.b.mode) { + regs->cur_fb_width = (base->fb_p->fb.fb_w*2); + pos_y /= 2; + crop_y /= 2; + height /= 2; + } else + regs->cur_fb_width = base->fb_p->fb.fb_w; + +/* DPRINT("[CURSOR] V pos %d,hotspot %d,posx %d,crop %d,height %d\n", + p_cursor->posy,p_cursor->hotspot_y,pos_y,crop_y,height); */ + + regs->cur_width = width; + regs->cur_vcrop = crop_y; + regs->cur_hcrop = crop_x; + govrh_CUR_set_coordinate(base, pos_x, pos_y, + pos_x + width - 1, pos_y + height - 1); + return 0; +} + +void govrh_CUR_irqproc(int arg) +{ + if (p_cursor->enable) { + if (p_cursor->chg_flag) { + p_cursor->hide_cnt = 0; + govrh_CUR_set_enable(p_cursor, 1); + } else { + p_cursor->hide_cnt++; + if (p_cursor->hide_cnt > + (GOVRH_CURSOR_HIDE_TIME * p_govrh->fb_p->framerate)) + govrh_CUR_set_enable(p_cursor, 0); + } + } + + if (p_cursor->chg_flag) { + govrh_irqproc_set_position(p_cursor); + p_cursor->chg_flag = 0; + } +} + +void govrh_CUR_proc_view(struct govrh_cursor_mod_t *base, + int read, vdo_view_t *view) +{ + vdo_framebuf_t *fb; + + DBG_DETAIL("(0x%x)\n", base->mmio); + + fb = &base->fb_p->fb; + if (read) { + view->resx_src = fb->fb_w; + view->resy_src = fb->fb_h; + view->resx_virtual = fb->img_w; + view->resy_virtual = fb->img_h; + view->resx_visual = fb->img_w; + view->resy_visual = fb->img_h; + view->posx = base->posx; + view->posy = base->posy; + view->offsetx = fb->h_crop; + view->offsety = fb->v_crop; + } else { + base->posx = view->posx; + base->posy = view->posy; + base->chg_flag = 1; + } +} + +void govrh_CUR_set_framebuffer(struct govrh_cursor_mod_t *base, + vdo_framebuf_t *fb) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base); + + DBG_DETAIL("(0x%x)\n", base->mmio); + + regs->cur_addr = fb->y_addr; + regs->cur_width = fb->img_w; + if (regs->tg_enable.b.mode) + regs->cur_fb_width = (fb->fb_w*2); + else + regs->cur_fb_width = fb->fb_w; + regs->cur_vcrop = fb->v_crop; + regs->cur_hcrop = fb->h_crop; + regs->cur_status.b.out_field = vpp_get_fb_field(fb); + govrh_irqproc_set_position(base); + base->colfmt = fb->col_fmt; + base->cursor_addr1 = fb->y_addr; +#ifdef __KERNEL__ + if (base->cursor_addr2 == 0) + base->cursor_addr2 = mb_alloc(64*64*4); +#endif + vpp_cache_sync(); +} + +void govrh_CUR_init(void *base) +{ +#ifdef CONFIG_GOVR2_CURSOR + HW_REG struct govrh_regs *regs; + + regs = (HW_REG struct govrh_regs *) p_govrh->mmio; + regs->cur_color_key.b.invert = 1; + regs = (HW_REG struct govrh_regs *) p_govrh2->mmio; + regs->cur_color_key.b.invert = 1; +#else + struct govrh_cursor_mod_t *mod_p; + HW_REG struct govrh_regs *regs; + + mod_p = (struct govrh_cursor_mod_t *) base; + regs = (HW_REG struct govrh_regs *) mod_p->mmio; + + regs->cur_color_key.b.invert = 1; +#endif +} +#endif /* WMT_FTBLK_GOVRH_CURSOR */ + +/*----------------------- GOVRH API --------------------------------------*/ +void govrh_vmode_to_timing(vpp_mod_t mod, + struct fb_videomode *vmode, vpp_clock_t *t) +{ + unsigned int pixel_clock; + int temp; + + t->begin_pixel_of_active = vmode->hsync_len + vmode->left_margin; + t->end_pixel_of_active = t->begin_pixel_of_active + vmode->xres; + t->total_pixel_of_line = t->end_pixel_of_active + vmode->right_margin; + t->begin_line_of_active = vmode->vsync_len + vmode->upper_margin; + t->end_line_of_active = t->begin_line_of_active + vmode->yres; + t->total_line_of_frame = t->end_line_of_active + vmode->lower_margin; + t->line_number_between_VBIS_VBIE = vmode->vsync_len + 1; + temp = t->total_line_of_frame - t->end_line_of_active; + t->line_number_between_PVBI_VBIS = (temp > 2) ? (temp-1) : 1; + t->hsync = vmode->hsync_len; + t->vsync = vmode->vsync_len; + + pixel_clock = PICOS2KHZ(vmode->pixclock) * 1000; + t->read_cycle = vpp_get_base_clock(mod) / pixel_clock; +} + +void govrh_set_videomode(struct govrh_mod_t *base, + struct fb_videomode *p_vmode) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + struct fb_videomode vmode; + vpp_clock_t t1; + int tg_enable; + + DBG_MSG("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + tg_enable = regs->tg_enable.b.enable; + regs->tg_enable.b.enable = 0; + + vmode = *p_vmode; + if (vmode.vmode & FB_VMODE_DOUBLE) { + vmode.xres *= 2; + DBGMSG("[GOVRH] H scale up\n"); + } + + if (vmode.vmode & FB_VMODE_INTERLACED) { + vmode.vsync_len /= 2; + vmode.upper_margin /= 2; + vmode.yres /= 2; + vmode.lower_margin /= 2; + } + + govrh_vmode_to_timing(base->mod, &vmode, &t1); + t1.read_cycle = govrh_set_clock(base, PICOS2KHZ(vmode.pixclock)*1000); + if (vmode.vmode & FB_VMODE_INTERLACED) { + t1.total_line_of_frame += 1; + t1.begin_line_of_active += 1; + t1.end_line_of_active += 1; + t1.vsync += 1; + } + govrh_set_tg1(base, &t1); + + if (vmode.vmode & FB_VMODE_INTERLACED) { + vpp_clock_t t2; + + vmode.upper_margin += 1; + /* 480i/576i repeat 2 pixel */ + if (vmode.vmode & FB_VMODE_DOUBLE) + vmode.xres *= 2; + govrh_vmode_to_timing(base->mod, &vmode, &t2); + t2.total_line_of_frame -= 1; + t2.vsync += 1; + govrh_set_tg2(base, &t2); + } + govrh_set_output_format(base, + (vmode.vmode & FB_VMODE_INTERLACED) ? 1 : 0); + regs->hscale_up = (vmode.vmode & FB_VMODE_DOUBLE) ? 1 : 0; + regs->vsync_offset.val = (vmode.vmode & FB_VMODE_INTERLACED) ? + ((regs->h_allpxl / 2) | BIT16) : 0; + + regs->tg_enable.b.enable = tg_enable; +} + +void govrh_get_videomode(struct govrh_mod_t *base, + struct fb_videomode *vmode) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + vpp_clock_t t; + int htotal, vtotal; + unsigned int pixel_clock; + + vmode->flag = FB_MODE_IS_FROM_VAR; + vmode->name = 0; + + govrh_get_tg(base, &t); + pixel_clock = vpp_get_base_clock(base->mod); + vmode->pixclock = KHZ2PICOS(pixel_clock/1000); + + vmode->hsync_len = t.hsync; + vmode->left_margin = t.begin_pixel_of_active - t.hsync; + vmode->xres = t.end_pixel_of_active - t.begin_pixel_of_active; + vmode->right_margin = t.total_pixel_of_line - t.end_pixel_of_active; + + vmode->vsync_len = t.vsync; + vmode->upper_margin = t.begin_line_of_active - t.vsync; + vmode->yres = t.end_line_of_active - t.begin_line_of_active; + vmode->lower_margin = t.total_line_of_frame - t.end_line_of_active; + + htotal = vmode->xres + vmode->right_margin + + vmode->hsync_len + vmode->left_margin; + vtotal = vmode->yres + vmode->lower_margin + + vmode->vsync_len + vmode->upper_margin; + vmode->vmode = (regs->tg_enable.b.mode) ? FB_VMODE_INTERLACED : 0; + if (vmode->vmode & FB_VMODE_INTERLACED) + vtotal /= 2; + if (vmode->vmode & FB_VMODE_DOUBLE) + vtotal *= 2; + + if (htotal && vtotal) { + unsigned int temp; + temp = (pixel_clock * 10)/(htotal * vtotal); + vmode->refresh = temp / 10; + if ((temp % 10) >= 5) + vmode->refresh += 1; + } else + vmode->refresh = 60; + + { /* get sync polar */ + int hsync_hi, vsync_hi; + enum vout_inf_mode_t interface; + + switch (base->mod) { + case VPP_MOD_GOVRH: + interface = VOUT_INF_HDMI; + break; + case VPP_MOD_GOVRH2: + interface = VOUT_INF_DVI; + if (lcd_get_type()) + interface = VOUT_INF_LVDS; + break; + default: + interface = VOUT_INF_DVI; + break; + } + + switch (interface) { + case VOUT_INF_DVI: + hsync_hi = (regs->dvo_set.b.hsync_polar) ? 0 : 1; + vsync_hi = (regs->dvo_set.b.vsync_polar) ? 0 : 1; + break; + case VOUT_INF_HDMI: + vo_hdmi_set_clock(1); + hdmi_get_sync_polar(&hsync_hi, &vsync_hi); + vo_hdmi_set_clock(0); + break; + case VOUT_INF_LVDS: + lvds_get_sync_polar(&hsync_hi, &vsync_hi); + break; + default: + hsync_hi = 0; + vsync_hi = 0; + break; + } + vmode->sync = (hsync_hi) ? FB_SYNC_HOR_HIGH_ACT : 0; + vmode->sync |= (vsync_hi) ? FB_SYNC_VERT_HIGH_ACT : 0; + } +} + +void govrh_set_framebuffer(struct govrh_mod_t *base, vdo_framebuf_t *fb) +{ + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + govrh_set_fb_addr(base, fb->y_addr, fb->c_addr); + govrh_set_color_format(base, fb->col_fmt); + govrh_set_fb_info(base, fb->fb_w, fb->img_w, fb->h_crop, fb->v_crop); + govrh_set_source_format(base, vpp_get_fb_field(fb)); + govrh_set_csc_mode(base, base->fb_p->csc_mode); +} + +void govrh_get_framebuffer(struct govrh_mod_t *base, vdo_framebuf_t *fb) +{ + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + vpp_clock_t clock; + int y_bpp, c_bpp; + + DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2); + + govrh_get_fb_addr(base, &fb->y_addr, &fb->c_addr); + fb->col_fmt = govrh_get_color_format(base); + govrh_get_fb_info(base, &fb->fb_w, + &fb->img_w, &fb->h_crop, &fb->v_crop); + govrh_get_tg(base, &clock); + fb->img_h = clock.end_line_of_active - clock.begin_line_of_active; + fb->fb_h = fb->img_h; + fb->flag = (regs->srcfmt) ? VDO_FLAG_INTERLACE : 0; + vpp_get_colfmt_bpp(fb->col_fmt, &y_bpp, &c_bpp); + fb->bpp = y_bpp + c_bpp; + fb->y_size = fb->fb_w * fb->fb_h * y_bpp / 8; + fb->c_size = fb->fb_w * fb->fb_h * c_bpp / 8; +} + +/*----------------------- GOVRH MODULE API -----------------------------*/ +int govrh_suspend_yaddr; +void govrh_suspend(struct govrh_mod_t *base, int sts) +{ +#ifdef CONFIG_PM + HW_REG struct govrh_regs *regs = + (HW_REG struct govrh_regs *) base->mmio; + + switch (sts) { + case 0: /* disable module */ + base->pm_enable = govrh_get_MIF_enable(base); + govrh_set_MIF_enable(base, 0); + break; + case 1: /* disable tg */ + base->pm_tg = regs->tg_enable.b.enable; + govrh_set_tg_enable(base, 0); + break; + case 2: /* backup register */ + base->reg_bk = vpp_backup_reg((unsigned int)base->mmio, + (REG_GOVRH_BASE2_END-REG_GOVRH_BASE1_BEGIN)); + if (base->vo_clock == 0) + base->vo_clock = vpp_get_base_clock(base->mod); + govrh_suspend_yaddr = 0; + break; + default: + break; + } +#endif +} + +void govrh_resume(struct govrh_mod_t *base, int sts) +{ +#ifdef CONFIG_PM + switch (sts) { + case 0: /* restore register */ + govrh_set_clock(base, base->vo_clock); + vpp_restore_reg((unsigned int)base->mmio, + (REG_GOVRH_BASE2_END-REG_GOVRH_BASE1_BEGIN), + base->reg_bk); + if (base == p_govrh && govrh_suspend_yaddr) + govrh_set_fb_addr(p_govrh, govrh_suspend_yaddr, 0); + base->reg_bk = 0; + break; + case 1: /* enable module */ + govrh_set_MIF_enable(base, base->pm_enable); + break; + case 2: /* enable tg */ + govrh_set_tg_enable(base, base->pm_tg); + break; + default: + break; + } +#endif +} + +void govrh_init(void *base) +{ + struct govrh_mod_t *mod_p; + HW_REG struct govrh_regs *regs; + + mod_p = (struct govrh_mod_t *) base; + regs = (HW_REG struct govrh_regs *) mod_p->mmio; + + govrh_set_reg_level(base, VPP_REG_LEVEL_1); + govrh_set_colorbar(base, VPP_FLAG_DISABLE, 1, 0); + govrh_set_tg_enable(base, VPP_FLAG_ENABLE); + govrh_set_dvo_color_format(base, VDO_COL_FMT_ARGB); + govrh_set_dvo_enable(base, VPP_FLAG_DISABLE); + + govrh_set_framebuffer(base, &mod_p->fb_p->fb); + govrh_set_fifo_index(base, 0xf); + govrh_set_csc_mode(base, mod_p->fb_p->csc_mode); + + govrh_set_reg_update(base, VPP_FLAG_ENABLE); + govrh_set_tg_enable(base, VPP_FLAG_ENABLE); +/* govrh_set_MIF_enable(base, VPP_FLAG_ENABLE); */ + govrh_set_int_enable(base, VPP_FLAG_ENABLE, mod_p->int_catch); +} + +void govrh_mod_dump_reg(void) +{ + govrh_reg_dump((void *)p_govrh); +} + +void govrh_mod_set_enable(vpp_flag_t enable) +{ + govrh_set_MIF_enable(p_govrh, enable); +} + +void govrh_mod_set_colorbar(vpp_flag_t enable, int mode, int inv) +{ + govrh_set_colorbar(p_govrh, enable, mode, inv); +} + +void govrh_mod_set_tg(vpp_clock_t *tmr, unsigned int pixel_clock) +{ + govrh_set_tg(p_govrh, tmr, pixel_clock); +} + +void govrh_mod_get_tg(vpp_clock_t *tmr) +{ + govrh_get_tg(p_govrh, tmr); +} + +unsigned int govrh_mod_get_sts(void) +{ + return govrh_get_int_status(p_govrh); +} + +void govrh_mod_clr_sts(unsigned int sts) +{ + govrh_clean_int_status(p_govrh, sts); +} + +void govrh_mod_suspend(int sts) +{ + govrh_suspend(p_govrh, sts); +} + +void govrh_mod_resume(int sts) +{ + govrh_resume(p_govrh, sts); +} + +void govrh_mod_set_framebuf(vdo_framebuf_t *fb) +{ + govrh_set_framebuffer(p_govrh, fb); +} +void govrh_mod_set_addr(unsigned int yaddr, unsigned int caddr) +{ + govrh_set_fb_addr(p_govrh, yaddr, caddr); +} +void govrh_mod_get_addr(unsigned int *yaddr, unsigned int *caddr) +{ + govrh_get_fb_addr(p_govrh, yaddr, caddr); +} +void govrh_mod_set_csc(vpp_csc_t mode) +{ + govrh_set_csc_mode(p_govrh, mode); +} +vdo_color_fmt govrh_mod_get_color_fmt(void) +{ + return govrh_get_color_format(p_govrh); +} +void govrh_mod_set_color_fmt(vdo_color_fmt colfmt) +{ + govrh_set_color_format(p_govrh, colfmt); +} + +#ifdef WMT_FTBLK_GOVRH_CURSOR +void cursor_mod_set_enable(vpp_flag_t enable) +{ + govrh_CUR_set_enable(p_cursor, enable); +} + +void cursor_mod_set_framebuf(vdo_framebuf_t *fb) +{ + govrh_CUR_set_framebuffer(p_cursor, fb); +} + +void cursor_mod_set_addr(unsigned int yaddr, unsigned int caddr) +{ + govrh_CUR_set_fb_addr(p_cursor, yaddr, caddr); +} + +void cursor_mod_get_addr(unsigned int *yaddr, unsigned int *caddr) +{ + govrh_CUR_get_fb_addr(p_cursor, yaddr, caddr); +} + +void cursor_mod_fn_view(int read, vdo_view_t *view) +{ + govrh_CUR_proc_view(p_cursor, read, view); +} +#endif + +#ifdef WMT_FTBLK_GOVRH2 +void govrh2_mod_dump_reg(void) +{ + govrh_reg_dump((void *)p_govrh2); +} + +void govrh2_mod_set_enable(vpp_flag_t enable) +{ + govrh_set_MIF_enable(p_govrh2, enable); +} + +void govrh2_mod_set_colorbar(vpp_flag_t enable, int mode, int inv) +{ + govrh_set_colorbar(p_govrh2, enable, mode, inv); +} + +void govrh2_mod_set_tg(vpp_clock_t *tmr, unsigned int pixel_clock) +{ + govrh_set_tg(p_govrh2, tmr, pixel_clock); +} + +void govrh2_mod_get_tg(vpp_clock_t *tmr) +{ + govrh_get_tg(p_govrh2, tmr); +} + +unsigned int govrh2_mod_get_sts(void) +{ + return govrh_get_int_status(p_govrh2); +} + +void govrh2_mod_clr_sts(unsigned int sts) +{ + govrh_clean_int_status(p_govrh2, sts); +} + +void govrh2_mod_suspend(int sts) +{ + govrh_suspend(p_govrh2, sts); +} + +void govrh2_mod_resume(int sts) +{ + govrh_resume(p_govrh2, sts); +} + +void govrh2_mod_set_framebuf(vdo_framebuf_t *fb) +{ + govrh_set_framebuffer(p_govrh2, fb); +} +void govrh2_mod_set_addr(unsigned int yaddr, unsigned int caddr) +{ + govrh_set_fb_addr(p_govrh2, yaddr, caddr); +} +void govrh2_mod_get_addr(unsigned int *yaddr, unsigned int *caddr) +{ + govrh_get_fb_addr(p_govrh2, yaddr, caddr); +} +void govrh2_mod_set_csc(vpp_csc_t mode) +{ + govrh_set_csc_mode(p_govrh2, mode); +} +vdo_color_fmt govrh2_mod_get_color_fmt(void) +{ + return govrh_get_color_format(p_govrh2); +} +void govrh2_mod_set_color_fmt(vdo_color_fmt colfmt) +{ + govrh_set_color_format(p_govrh2, colfmt); +} + +#endif +int govrh_mod_init(void) +{ + struct govrh_mod_t *mod_p; + struct vpp_fb_base_t *mod_fb_p; + vdo_framebuf_t *fb_p; + + mod_p = (struct govrh_mod_t *) vpp_mod_register(VPP_MOD_GOVRH, + sizeof(struct govrh_mod_t), + VPP_MOD_FLAG_FRAMEBUF); + if (!mod_p) { + DPRINT("*E* GOVRH module register fail\n"); + return -1; + } + + /* module member variable */ + mod_p->mmio = (void *)REG_GOVRH_BASE1_BEGIN; + mod_p->int_catch = VPP_INT_NULL; /* VPP_INT_ERR_GOVRH_MIF; */ + + /* module member function */ + mod_p->init = govrh_init; + mod_p->dump_reg = govrh_mod_dump_reg; + mod_p->set_enable = govrh_mod_set_enable; + mod_p->set_colorbar = govrh_mod_set_colorbar; + mod_p->set_tg = govrh_mod_set_tg; + mod_p->get_tg = govrh_mod_get_tg; + mod_p->get_sts = govrh_mod_get_sts; + mod_p->clr_sts = govrh_mod_clr_sts; + mod_p->suspend = govrh_mod_suspend; + mod_p->resume = govrh_mod_resume; + + /* module frame buffer */ + mod_fb_p = mod_p->fb_p; + mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_JFIF_0_255; + mod_fb_p->framerate = VPP_HD_DISP_FPS; + mod_fb_p->media_fmt = VPP_MEDIA_FMT_MPEG; + mod_fb_p->wait_ready = 0; + mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420) + | BIT(VDO_COL_FMT_YUV422H) + | BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB) + | BIT(VDO_COL_FMT_RGB_1555) | BIT(VDO_COL_FMT_RGB_565) + | VPP_FB_FLAG_CSC | VPP_FB_FLAG_MEDIA + | VPP_FB_FLAG_FIELD; + + /* module frame buffer member function */ + mod_fb_p->set_framebuf = govrh_mod_set_framebuf; + mod_fb_p->set_addr = govrh_mod_set_addr; + mod_fb_p->get_addr = govrh_mod_get_addr; + mod_fb_p->set_csc = govrh_mod_set_csc; + mod_fb_p->get_color_fmt = govrh_mod_get_color_fmt; + mod_fb_p->set_color_fmt = govrh_mod_set_color_fmt; + + fb_p = &mod_p->fb_p->fb; + fb_p->y_addr = 0; + fb_p->c_addr = 0; + fb_p->col_fmt = VPP_UBOOT_COLFMT; + fb_p->img_w = VPP_HD_DISP_RESX; + fb_p->img_h = VPP_HD_DISP_RESY; + fb_p->fb_w = VPP_HD_MAX_RESX; + fb_p->fb_h = VPP_HD_MAX_RESY; + fb_p->h_crop = 0; + fb_p->v_crop = 0; + fb_p->flag = 0; + + p_govrh = mod_p; + +#ifdef WMT_FTBLK_GOVRH_CURSOR + mod_p = (struct govrh_mod_t *) vpp_mod_register(VPP_MOD_CURSOR, + sizeof(struct govrh_cursor_mod_t), + VPP_MOD_FLAG_FRAMEBUF); + if (!mod_p) { + DPRINT("*E* CURSOR module register fail\n"); + return -1; + } + + /* module member function */ + mod_p->init = govrh_CUR_init; + mod_p->set_enable = cursor_mod_set_enable; + mod_p->mmio = (void *)REG_GOVRH_BASE1_BEGIN; + + /* module frame buffer */ + mod_fb_p = mod_p->fb_p; + mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255; + mod_fb_p->framerate = VPP_HD_DISP_FPS; + mod_fb_p->media_fmt = VPP_MEDIA_FMT_MPEG; + mod_fb_p->wait_ready = 0; + mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420) + | BIT(VDO_COL_FMT_YUV422H) + | BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB) + | VPP_FB_FLAG_CSC | VPP_FB_FLAG_MEDIA + | VPP_FB_FLAG_FIELD; + + /* module frame buffer member function */ + mod_fb_p->set_framebuf = cursor_mod_set_framebuf; + mod_fb_p->set_addr = cursor_mod_set_addr; + mod_fb_p->get_addr = cursor_mod_get_addr; + mod_fb_p->fn_view = cursor_mod_fn_view; + + fb_p = &mod_p->fb_p->fb; + fb_p->y_addr = 0; + fb_p->c_addr = 0; + fb_p->col_fmt = VDO_COL_FMT_YUV444; + fb_p->img_w = VPP_HD_DISP_RESX; + fb_p->img_h = VPP_HD_DISP_RESY; + fb_p->fb_w = VPP_HD_MAX_RESX; + fb_p->fb_h = VPP_HD_MAX_RESY; + fb_p->h_crop = 0; + fb_p->v_crop = 0; + fb_p->flag = 0; + + p_cursor = (struct govrh_cursor_mod_t *) mod_p; +#endif + +#ifdef WMT_FTBLK_GOVRH2 + mod_p = (struct govrh_mod_t *) vpp_mod_register(VPP_MOD_GOVRH2, + sizeof(struct govrh_mod_t), + VPP_MOD_FLAG_FRAMEBUF); + if (!mod_p) { + DPRINT("*E* GOVRH module register fail\n"); + return -1; + } + + /* module member variable */ + mod_p->mmio = (void *)REG_GOVRH2_BASE1_BEGIN; + mod_p->int_catch = VPP_INT_NULL; /* VPP_INT_ERR_GOVRH_MIF; */ + + /* module member function */ + mod_p->init = govrh_init; + mod_p->dump_reg = govrh2_mod_dump_reg; + mod_p->set_enable = govrh2_mod_set_enable; + mod_p->set_colorbar = govrh2_mod_set_colorbar; + mod_p->set_tg = govrh2_mod_set_tg; + mod_p->get_tg = govrh2_mod_get_tg; + mod_p->get_sts = govrh2_mod_get_sts; + mod_p->clr_sts = govrh2_mod_clr_sts; + mod_p->suspend = govrh2_mod_suspend; + mod_p->resume = govrh2_mod_resume; + + /* module frame buffer */ + mod_fb_p = mod_p->fb_p; + mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_JFIF_0_255; + mod_fb_p->framerate = VPP_HD_DISP_FPS; + mod_fb_p->media_fmt = VPP_MEDIA_FMT_MPEG; + mod_fb_p->wait_ready = 0; + mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420) + | BIT(VDO_COL_FMT_YUV422H) + | BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB) + | BIT(VDO_COL_FMT_RGB_1555) | BIT(VDO_COL_FMT_RGB_565) + | VPP_FB_FLAG_CSC | VPP_FB_FLAG_MEDIA | VPP_FB_FLAG_FIELD; + + /* module frame buffer member function */ + mod_fb_p->set_framebuf = govrh2_mod_set_framebuf; + mod_fb_p->set_addr = govrh2_mod_set_addr; + mod_fb_p->get_addr = govrh2_mod_get_addr; + mod_fb_p->set_csc = govrh2_mod_set_csc; + mod_fb_p->get_color_fmt = govrh2_mod_get_color_fmt; + mod_fb_p->set_color_fmt = govrh2_mod_set_color_fmt; + + fb_p = &mod_p->fb_p->fb; + fb_p->y_addr = 0; + fb_p->c_addr = 0; + fb_p->col_fmt = VPP_UBOOT_COLFMT; + fb_p->img_w = VPP_HD_DISP_RESX; + fb_p->img_h = VPP_HD_DISP_RESY; + fb_p->fb_w = VPP_HD_MAX_RESX; + fb_p->fb_h = VPP_HD_MAX_RESY; + fb_p->h_crop = 0; + fb_p->v_crop = 0; + fb_p->flag = 0; + + p_govrh2 = mod_p; +#endif + return 0; +} +module_init(govrh_mod_init); +#endif /* WMT_FTBLK_GOVRH */ diff --git a/common/wmt_display/govrh.h b/common/wmt_display/govrh.h new file mode 100755 index 0000000..a7dc062 --- /dev/null +++ b/common/wmt_display/govrh.h @@ -0,0 +1,184 @@ +/*++ + * linux/drivers/video/wmt/govrh.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include "vpp.h" + +#ifdef WMT_FTBLK_GOVRH + +#ifndef GOVRH_H +#define GOVRH_H + +struct govrh_mod_t { + VPP_MOD_BASE; + + unsigned int *reg_bk2; + unsigned int pm_enable; + unsigned int pm_tg; + unsigned int vo_clock; + unsigned int underrun_cnt; + unsigned int csc_mode_force; +}; + +#ifdef WMT_FTBLK_GOVRH_CURSOR +#define GOVRH_CURSOR_HIDE_TIME 15 +struct govrh_cursor_mod_t { + VPP_MOD_BASE; + + unsigned int posx; + unsigned int posy; + unsigned int hotspot_x; + unsigned int hotspot_y; + int chg_flag; + vdo_color_fmt colfmt; + unsigned int cursor_addr1; + unsigned int cursor_addr2; + int enable; + int hide_cnt; +}; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef GOVRH_C +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN struct govrh_mod_t *p_govrh; +#ifdef WMT_FTBLK_GOVRH_CURSOR +EXTERN struct govrh_cursor_mod_t *p_cursor; +#endif +#ifdef WMT_FTBLK_GOVRH2 +EXTERN struct govrh_mod_t *p_govrh2; +#endif + +EXTERN void govrh_set_tg_enable(struct govrh_mod_t *base, + vpp_flag_t enable); +EXTERN int govrh_get_tg_mode(struct govrh_mod_t *base); +EXTERN int govrh_get_hscale_up(struct govrh_mod_t *base); +EXTERN void govrh_set_direct_path(struct govrh_mod_t *base, int enable); +EXTERN int govrh_get_dvo_enable(struct govrh_mod_t *base); +EXTERN void govrh_set_dvo_enable(struct govrh_mod_t *base, + vpp_flag_t enable); +EXTERN void govrh_set_dvo_sync_polar(struct govrh_mod_t *base, + vpp_flag_t hsync, vpp_flag_t vsync); +EXTERN void govrh_set_dvo_outdatw(struct govrh_mod_t *base, + vpp_datawidht_t width); +EXTERN void govrh_set_dvo_clock_delay(struct govrh_mod_t *base, + int inverse, int delay); +EXTERN void govrh_set_colorbar(struct govrh_mod_t *base, + vpp_flag_t enable, int mode, int inv); +EXTERN void govrh_set_contrast(struct govrh_mod_t *base, + unsigned int value); +EXTERN unsigned int govrh_get_contrast(struct govrh_mod_t *base); +EXTERN void govrh_set_brightness(struct govrh_mod_t *base, + unsigned int value); +EXTERN unsigned int govrh_get_brightness(struct govrh_mod_t *base); +EXTERN void govrh_set_saturation(struct govrh_mod_t *base, unsigned int value); +EXTERN unsigned int govrh_get_saturation(struct govrh_mod_t *base); +EXTERN void govrh_set_MIF_enable(struct govrh_mod_t *base, vpp_flag_t enable); +EXTERN int govrh_get_MIF_enable(struct govrh_mod_t *base); +EXTERN void govrh_set_color_format(struct govrh_mod_t *base, + vdo_color_fmt format); +EXTERN vdo_color_fmt govrh_get_color_format(struct govrh_mod_t *base); +EXTERN void govrh_set_source_format(struct govrh_mod_t *base, + vpp_display_format_t format); +EXTERN void govrh_set_output_format(struct govrh_mod_t *base, + vpp_display_format_t field); +EXTERN void govrh_set_fb_addr(struct govrh_mod_t *base, + unsigned int y_addr, unsigned int c_addr); +EXTERN void govrh_get_fb_addr(struct govrh_mod_t *base, + unsigned int *y_addr, unsigned int *c_addr); +EXTERN void govrh_set_fb_width(struct govrh_mod_t *base, + unsigned int width); +EXTERN void govrh_set_fb_info(struct govrh_mod_t *base, + unsigned int width, unsigned int act_width, + unsigned int x_offset, unsigned int y_offset); +EXTERN void govrh_get_fb_info(struct govrh_mod_t *base, + unsigned int *width, unsigned int *act_width, + unsigned int *x_offset, unsigned int *y_offset); +EXTERN void govrh_set_fifo_index(struct govrh_mod_t *base, + unsigned int index); +EXTERN void govrh_set_reg_level(struct govrh_mod_t *base, + vpp_reglevel_t level); +EXTERN void govrh_set_reg_update(struct govrh_mod_t *base, + vpp_flag_t enable); +EXTERN void govrh_set_csc_mode(struct govrh_mod_t *base, + vpp_csc_t mode); +EXTERN void govrh_set_framebuffer(struct govrh_mod_t *base, + vdo_framebuf_t *inbuf); +EXTERN void govrh_get_framebuffer(struct govrh_mod_t *base, + vdo_framebuf_t *fb); +EXTERN vdo_color_fmt govrh_get_dvo_color_format( + struct govrh_mod_t *base); +EXTERN void govrh_set_dvo_color_format(struct govrh_mod_t *base, + vdo_color_fmt fmt); +EXTERN enum vpp_int_err_t govrh_get_int_status(struct govrh_mod_t *base); +EXTERN void govrh_clean_int_status(struct govrh_mod_t *base, + enum vpp_int_err_t int_sts); +EXTERN unsigned int govrh_set_clock(struct govrh_mod_t *base, + unsigned int pixel_clock); +EXTERN void govrh_set_videomode(struct govrh_mod_t *base, + struct fb_videomode *vmode); +EXTERN void govrh_get_tg(struct govrh_mod_t *base, vpp_clock_t *tmr); +EXTERN void govrh_get_videomode(struct govrh_mod_t *base, + struct fb_videomode *vmode); +EXTERN void govrh_HDMI_set_blank_value(struct govrh_mod_t *base, + unsigned int val); +EXTERN void govrh_HDMI_set_3D_mode(struct govrh_mod_t *base, + int mode); +EXTERN int govrh_is_top_field(struct govrh_mod_t *base); +EXTERN void govrh_IGS_set_mode(struct govrh_mod_t *base, + int no, int mode_18bit, int msb); +EXTERN void govrh_IGS_set_RGB_swap(struct govrh_mod_t *base, + int mode); +EXTERN int govrh_mod_init(void); + +#ifdef WMT_FTBLK_GOVRH_CURSOR +EXTERN void govrh_CUR_set_enable(struct govrh_cursor_mod_t *base, + vpp_flag_t enable); +EXTERN void govrh_CUR_set_framebuffer(struct govrh_cursor_mod_t *base, + vdo_framebuf_t *fb); +EXTERN void govrh_CUR_set_coordinate(struct govrh_cursor_mod_t *base, + unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2); +EXTERN void govrh_CUR_set_position(struct govrh_cursor_mod_t *base, + unsigned int x, unsigned int y); +EXTERN void govrh_CUR_set_color_key_mode(struct govrh_cursor_mod_t *base, + int alpha, int enable, int mode); +EXTERN void govrh_CUR_set_color_key(struct govrh_cursor_mod_t *base, + int enable, int alpha, unsigned int colkey); +EXTERN void govrh_CUR_set_colfmt(struct govrh_cursor_mod_t *base, + vdo_color_fmt colfmt); +EXTERN void govrh_CUR_irqproc(int arg); +#endif + +#undef EXTERN + +#ifdef __cplusplus +} +#endif +#endif /* GOVRH_H */ +#endif /* WMT_FTBLK_GOVRH */ diff --git a/common/wmt_display/hdmi.c b/common/wmt_display/hdmi.c new file mode 100755 index 0000000..c181d75 --- /dev/null +++ b/common/wmt_display/hdmi.c @@ -0,0 +1,1457 @@ +/*++ + * linux/drivers/video/wmt/hdmi.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define HDMI_C +#undef DEBUG +/* #define DEBUG */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "hdmi.h" +#include "vout.h" +#ifdef __KERNEL__ +#include <asm/div64.h> +#endif + +/*----------------------- PRIVATE MACRO --------------------------------------*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define HDMI_XXXX 1 *//*Example*/ +/* #define CONFIG_HDMI_INFOFRAME_DISABLE */ +/* #define CONFIG_HDMI_EDID_DISABLE */ + +#define HDMI_I2C_FREQ 80000 +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx hdmi_xxx_t; *//*Example*/ +enum hdmi_fifo_slot_t { + HDMI_FIFO_SLOT_AVI = 0, + HDMI_FIFO_SLOT_VENDOR = 1, + HDMI_FIFO_SLOT_AUDIO = 2, + HDMI_FIFO_SLOT_CONTROL = 3, + HDMI_FIFO_SLOT_MAX = 15 +}; + +/*----------EXPORTED PRIVATE VARIABLES are defined in hdmi.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int hdmi_xxx; *//*Example*/ + +HW_REG struct hdmi_base1_regs *hdmi_regs1 = (void *) (HDMI_BASE_ADDR + 0x100); +HW_REG struct hdmi_base2_regs *hdmi_regs2 = (void *) HDMI_BASE2_ADDR; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void hdmi_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +/*---------------------------- HDMI COMMON API -------------------------------*/ +unsigned char hdmi_ecc(unsigned char *buf, int bit_cnt) +{ + #define HDMI_CRC_LEN 9 + + int crc[HDMI_CRC_LEN], crc_o[HDMI_CRC_LEN]; + int i, j; + int input, result, result_rev = 0; + + for (i = 0; i < HDMI_CRC_LEN; i++) + crc[i] = 0; + + for (i = 0; i < bit_cnt; i++) { + for (j = 0; j < HDMI_CRC_LEN; j++) + crc_o[j] = crc[j]; + input = (buf[i/8] & (1<<(i%8))) ? 1 : 0; + crc[0] = crc_o[7] ^ input; + crc[1] = crc_o[0]; + crc[2] = crc_o[1]; + crc[3] = crc_o[2]; + crc[4] = crc_o[3]; + crc[5] = crc_o[4]; + crc[6] = crc_o[5] ^ crc_o[7] ^ input; + crc[7] = crc_o[6] ^ crc_o[7] ^ input; + crc[8] = crc_o[7]; + + result = 0; + result_rev = 0; + for (j = 0; j < HDMI_CRC_LEN - 1; j++) { + result += (crc[j] << j); + result_rev += (crc[j] << (HDMI_CRC_LEN - 2 - j)); + } + } + +/* DPRINT("[HDMI] crc 0x%x, %x %x %x %x %x %x %x\n",result_rev, + buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6]); */ + return result_rev; +} + +unsigned char hdmi_checksum(unsigned char *header, + unsigned char *buf, int cnt) +{ + unsigned char sum; + int i; + + for (i = 0, sum = 0; i < cnt; i++) + sum += buf[i]; + for (i = 0; i < 3; i++) + sum += header[i]; + return 0 - sum; +} + +#ifdef WMT_FTBLK_HDMI +/*---------------------------- HDMI HAL --------------------------------------*/ +void hdmi_set_power_down(int pwrdn) +{ + DBG_DETAIL("(%d)\n", pwrdn); + + if ((hdmi_regs2->test.b.pd == 0) && (pwrdn == 0)) + return; /* avoid HDMI reset */ + + hdmi_regs2->status.b.internal_ldo = (pwrdn) ? 0 : 1; + hdmi_regs2->test.b.pd = pwrdn; + if (!pwrdn) { + hdmi_regs2->dftset2.b.reset_pll = 1; + mdelay(1); + hdmi_regs2->dftset2.b.reset_pll = 0; + } + mdelay(1); + hdmi_regs2->test2.b.pd_l2ha = pwrdn; +} + +int hdmi_get_power_down(void) +{ + return hdmi_regs2->test.b.pd; +} + +void hdmi_set_enable(vpp_flag_t enable) +{ + hdmi_regs1->general_ctrl.b.enable = enable; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */ + hdmi_regs2->test2.b.mode = (enable) ? 0 : 1; +} + +void hdmi_set_avmute(vpp_flag_t mute) +{ + hdmi_regs1->aud_insert_ctrl.b.avmute_set_enable = mute; +} + +void hdmi_set_dvi_enable(vpp_flag_t enable) +{ + hdmi_regs1->general_ctrl.b.dvi_mode_enable = enable; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */ +} + +void hdmi_set_sync_low_active(vpp_flag_t hsync, vpp_flag_t vsync) +{ + hdmi_regs1->general_ctrl.b.hsync_low_active = hsync; + hdmi_regs1->general_ctrl.b.vsync_low_active = vsync; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */ +} + +void hdmi_get_sync_polar(int *hsync_hi, int *vsync_hi) +{ + *hsync_hi = (hdmi_regs1->general_ctrl.b.hsync_low_active) ? 0 : 1; + *vsync_hi = (hdmi_regs1->general_ctrl.b.vsync_low_active) ? 0 : 1; +} + +void hdmi_set_output_colfmt(vdo_color_fmt colfmt) +{ + unsigned int val; + + switch (colfmt) { + default: + case VDO_COL_FMT_ARGB: + val = 0; + break; + case VDO_COL_FMT_YUV444: + val = 1; + break; + case VDO_COL_FMT_YUV422H: + case VDO_COL_FMT_YUV422V: + val = 2; + break; + } + hdmi_regs1->general_ctrl.b.convert_yuv422 = (val == 2) ? 1 : 0; + hdmi_regs1->general_ctrl.b.output_format = val; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */ +} + +vdo_color_fmt hdmi_get_output_colfmt(void) +{ + unsigned int val; + + val = hdmi_regs1->general_ctrl.b.output_format; + switch (val) { + default: + case 0: + return VDO_COL_FMT_ARGB; + case 1: + return VDO_COL_FMT_YUV444; + case 2: + return VDO_COL_FMT_YUV422H; + } + return VDO_COL_FMT_ARGB; +} + +int hdmi_get_plugin(void) +{ + int plugin; + + if (hdmi_regs1->hotplug_detect.b.in_enable) { + plugin = hdmi_regs1->hotplug_detect.b.sts; + } else { + int tre_en; + + tre_en = hdmi_regs2->test.b.tre_en; + hdmi_regs2->test.b.tre_en = 0; + plugin = hdmi_regs2->detect.b.rsen; + hdmi_regs2->test.b.tre_en = tre_en; + } + return plugin; +} + +int hdmi_get_plug_status(void) +{ + int reg; + + reg = hdmi_regs1->hotplug_detect.val; + return reg & 0x3000000; +} + +void hdmi_clear_plug_status(void) +{ + hdmi_regs1->hotplug_detect.b.in_sts = 1; + hdmi_regs1->hotplug_detect.b.out_sts = 1; +} + +void hdmi_enable_plugin(int enable) +{ + hdmi_regs1->hotplug_detect.b.out_enable = enable; + hdmi_regs1->hotplug_detect.b.in_enable = enable; +} + +void hdmi_write_fifo(enum hdmi_fifo_slot_t no, unsigned int *buf, int cnt) +{ + int i; + + if (no > HDMI_FIFO_SLOT_MAX) + return; +#ifdef DEBUG +{ + char *ptr; + + DPRINT("[HDMI] wr fifo %d,cnt %d", no, cnt); + ptr = (char *) buf; + for (i = 0; i < cnt; i++) { + if ((i % 4) == 0) + DPRINT("\n %02d :", i); + DPRINT(" 0x%02x", ptr[i]); + } + DPRINT("\n[HDMI] AVI info package end\n"); +} +#endif + hdmi_regs1->fifo_ctrl.val = (no << 8); + cnt = (cnt + 3) / 4; + for (i = 0; i < cnt; i++) + hdmi_regs1->wr_fifo_addr[i] = buf[i]; + hdmi_regs1->fifo_ctrl.b.wr_strobe = 1; +} + +void hdmi_read_fifo(enum hdmi_fifo_slot_t no, unsigned int *buf, int cnt) +{ + int i; + int rdy; + + if (no > HDMI_FIFO_SLOT_MAX) + return; + + rdy = hdmi_regs1->infoframe_ctrl.b.fifo1_rdy; + hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 0; + + no = no - 1; + hdmi_regs1->fifo_ctrl.val = (no << 8); + hdmi_regs1->fifo_ctrl.b.rd_strobe = 1; + cnt = (cnt + 3) / 4; + for (i = 0; i < cnt; i++) + buf[i] = hdmi_regs1->rd_fifo_addr[i]; + hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = rdy; +#ifdef DEBUG +{ + char *ptr; + + cnt *= 4; + DPRINT("[HDMI] rd fifo %d,cnt %d", no, cnt); + ptr = (char *) buf; + for (i = 0; i < cnt; i++) { + if ((i % 4) == 0) + DPRINT("\n %02d :", i); + DPRINT(" 0x%02x", ptr[i]); + } + DPRINT("\n[HDMI] AVI info package end\n"); +} +#endif +} + +#if 1 +int hdmi_ddc_delay_us = 5; +int hdmi_ddc_ctrl_delay_us = 5; + +#define HDMI_DDC_OUT +#define HDMI_DDC_DELAY hdmi_ddc_delay_us +#define HDMI_DDC_CHK_DELAY 1 +#define HDMI_DDC_CTRL_DELAY hdmi_ddc_ctrl_delay_us +#else +#define HDMI_DDC_OUT +#define HDMI_DDC_DELAY 1 +#define HDMI_DDC_CHK_DELAY 1 +#define HDMI_DDC_CTRL_DELAY 1 +#endif + +#define HDMI_STATUS_START BIT16 +#define HDMI_STATUS_STOP BIT17 +#define HDMI_STATUS_WR_AVAIL BIT18 +#define HDMI_STATUS_CP_USE BIT19 +#define HDMI_STATUS_SW_READ BIT25 +int hdmi_DDC_check_status(unsigned int checkbits, int condition) +{ + int status = 1; + unsigned int i = 0, maxloop; + + maxloop = 500 / HDMI_DDC_CHK_DELAY; + udelay(HDMI_DDC_DELAY); + + if (condition) { /* wait 1 --> 0 */ + while ((hdmi_regs1->i2c_ctrl2.val & checkbits) + && (i < maxloop)) { + udelay(HDMI_DDC_CHK_DELAY); + if (++i == maxloop) + status = 0; + } + } else { /* wait 0 --> 1 */ + while (!(hdmi_regs1->i2c_ctrl2.val & checkbits) + && (i < maxloop)) { + udelay(HDMI_DDC_CHK_DELAY); + if (++i == maxloop) + status = 0; + } + } + + if ((status == 0) && (checkbits != HDMI_STATUS_SW_READ)) { + unsigned int reg; + + reg = hdmi_regs1->i2c_ctrl2.val; + DBG_DETAIL("[HDMI] status timeout check 0x%x,wait to %s\n", + checkbits, (condition) ? "0" : "1"); + DBG_DETAIL("[HDMI] 0x%x,sta %d,stop %d,wr %d,rd %d,cp %d\n", + reg, (reg & HDMI_STATUS_START) ? 1 : 0, + (reg & HDMI_STATUS_STOP) ? 1 : 0, + (reg & HDMI_STATUS_WR_AVAIL) ? 1 : 0, + (reg & HDMI_STATUS_SW_READ) ? 1 : 0, + (reg & HDMI_STATUS_CP_USE) ? 1 : 0); + } + return status; +} + +void hdmi_DDC_set_freq(unsigned int hz) +{ + unsigned int clock; + unsigned int div; + + clock = 25000000*15/100; /* RTC clock source */ + div = clock / hz; + + hdmi_regs1->i2c_ctrl.b.i2c_clk_divider = div; + DBG_DETAIL("[HDMI] set freq(%d,clk %d,div %d)\n", hz, clock, div); +} + +void hdmi_DDC_reset(void) +{ + hdmi_regs1->i2c_ctrl.b.i2c_sw_reset = 1; + udelay(1); + hdmi_regs1->i2c_ctrl.b.i2c_sw_reset = 0; +} + +int hdmi_DDC_read_func(char addr, int index, char *buf, int length) +{ + int status = 1; + unsigned int i = 0; + int err_cnt = 0; + + DBG_DETAIL("[HDMI] read DDC(index 0x%x,len %d),reg 0x%x\n", + index, length, hdmi_regs1->i2c_ctrl2.val); + +#ifdef CONFIG_HDMI_EDID_DISABLE + return status; +#endif + + hdmi_DDC_set_freq(g_vpp.hdmi_i2c_freq); + /* enhanced DDC read */ + if (index >= 256) { + /* sw start, write data avail */ + vppif_reg32_write((unsigned int) &hdmi_regs1->i2c_ctrl2, + BIT18 + BIT16, 16, 0x5); + udelay(HDMI_DDC_CTRL_DELAY); + /* wait start & wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_START + + HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* start\n"); + err_cnt++; + goto ddc_read_fail; + } + + /* Slave address */ + hdmi_regs1->i2c_ctrl2.b.wr_data = 0x60; + hdmi_regs1->i2c_ctrl2.b.wr_data_avail = 1; + udelay(HDMI_DDC_CTRL_DELAY); + /* wait wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* slave addr 0x%x\n", addr); + err_cnt++; + goto ddc_read_fail; + } + + /* Offset */ + hdmi_regs1->i2c_ctrl2.b.wr_data = 0x1; + hdmi_regs1->i2c_ctrl2.b.wr_data_avail = 1; + udelay(HDMI_DDC_CTRL_DELAY); + /* wait wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* index 0x%x\n", index); + err_cnt++; + goto ddc_read_fail; + } + index -= 256; + } + + /* START */ + hdmi_regs1->i2c_ctrl2.val = 0x50000; /* start & data avail */ + udelay(HDMI_DDC_CTRL_DELAY); + /* wait start & wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_START + + HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* start\n"); + err_cnt++; + goto ddc_read_fail; + } + + /* Slave address */ + hdmi_regs1->i2c_ctrl2.val = 0x400A0; /* addr & data avail */ + udelay(HDMI_DDC_CTRL_DELAY); + /* wait wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* slave addr 0x%x\n", addr); + err_cnt++; + goto ddc_read_fail; + } + + /* Offset */ + hdmi_regs1->i2c_ctrl2.val = (0x40000 + index); /* index & data avail */ + udelay(HDMI_DDC_CTRL_DELAY); + /* wait wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* index 0x%x\n", index); + err_cnt++; + goto ddc_read_fail; + } + + /* START */ + hdmi_regs1->i2c_ctrl2.val = 0x50000; /* start & data avail */ + udelay(HDMI_DDC_CTRL_DELAY); + /* wait start & wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_START + + HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* restart\n"); + err_cnt++; + goto ddc_read_fail; + } + + /* Slave Address + 1 */ + hdmi_regs1->i2c_ctrl2.val = 0x400A1; /* addr(rd) & data avail */ + udelay(HDMI_DDC_CTRL_DELAY); + /* wait wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* slave addr 0x%x\n", addr + 1); + err_cnt++; + goto ddc_read_fail; + } + + /* Read Data */ + for (i = 0; i < length; i++) { + hdmi_regs1->i2c_ctrl2.val = 0x40000; /* data avail */ + udelay(HDMI_DDC_CTRL_DELAY); + /* wait wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* wr ACK(%d)\n", i); + err_cnt++; + goto ddc_read_fail; + /* break; */ + } + + /* wait sw read not set */ + status = hdmi_DDC_check_status(HDMI_STATUS_SW_READ, 0); + if (status == 0) { + DBGMSG("[HDMI] *E* read avail(%d)\n", i); + if (i == 0) { + err_cnt++; + /* goto ddc_read_fail; */ + } else { + /* g_vpp.dbg_hdmi_ddc_read_err++; */ + } + goto ddc_read_fail; + /* break; */ + } + + *buf++ = hdmi_regs1->i2c_ctrl2.b.rd_data; + udelay(HDMI_DDC_DELAY); + hdmi_regs1->i2c_ctrl2.val = 0x2000000; /* clr sw read */ + udelay(HDMI_DDC_DELAY); + } + + /* STOP */ + /* sw stop, write data avail */ + vppif_reg32_write((unsigned int) &hdmi_regs1->i2c_ctrl2.val, + BIT18 + BIT17, 17, 3); + udelay(HDMI_DDC_CTRL_DELAY); + /* wait start & wr data avail */ + status = hdmi_DDC_check_status(HDMI_STATUS_STOP + + HDMI_STATUS_WR_AVAIL + HDMI_STATUS_CP_USE, 1); + if (status == 0) { + DBGMSG("[HDMI] *E* stop\n"); + err_cnt++; + goto ddc_read_fail; + } + udelay(HDMI_DDC_DELAY); + +ddc_read_fail: + if (err_cnt) + DBGMSG("[HDMI] *E* read DDC %d\n", err_cnt); + return (err_cnt) ? 1 : 0; +} + +int hdmi_DDC_read(char addr, int index, char *buf, int length) +{ + int retry = 3; + int ret; + + DBG_MSG("(0x%x,0x%x,%d)\n", addr, index, length); + + do { + ret = hdmi_DDC_read_func(addr, index, buf, length); + if (ret == 0) + break; + hdmi_DDC_reset(); + DPRINT("[HDMI] *W* DDC reset %d\n", ret); + retry--; + } while (retry); + + return (retry == 0) ? 1 : 0; +} + +void hdmi_audio_enable(vpp_flag_t enable) +{ + if (hdmi_regs1->aud_enable != enable) { + if (!enable) { +#ifdef CONFIG_KERNEL + msleep(5); +#endif + if (g_vpp.hdmi_ch_change) + REG32_VAL(I2S_BASE_ADDR + 0x188) = 0; + } + hdmi_regs1->aud_enable = (enable) ? 1 : 0; + } +} + +void hdmi_audio_mute(vpp_flag_t enable) +{ + hdmi_regs1->aud_ratio.b.mute = enable; +} + +/*----------------------- HDMI API --------------------------------------*/ +void hdmi_write_packet(unsigned int header, unsigned char *packet, + int cnt) +{ + unsigned char buf[36]; + int i; + enum hdmi_fifo_slot_t no; + +#ifdef CONFIG_HDMI_INFOFRAME_DISABLE + return; +#endif + memcpy(&buf[0], &header, 3); + buf[3] = hdmi_ecc((unsigned char *)&header, 24); + for (i = 0; i < cnt / 7; i++) { + memcpy(&buf[4+8*i], &packet[7*i], 7); + buf[11+8*i] = hdmi_ecc(&packet[7*i], 56); + } + + switch (header & 0xFF) { + case HDMI_PACKET_INFOFRAME_AVI: + no = HDMI_FIFO_SLOT_AVI; + break; + case HDMI_PACKET_INFOFRAME_AUDIO: + no = HDMI_FIFO_SLOT_AUDIO; + break; + case HDMI_PACKET_INFOFRAME_VENDOR: + no = HDMI_FIFO_SLOT_VENDOR; + break; + default: + no = HDMI_FIFO_SLOT_CONTROL; + break; + } + hdmi_write_fifo(no, (unsigned int *)buf, (4 + 8 * (cnt / 7))); +} + +void hdmi_tx_null_packet(void) +{ + hdmi_write_packet(HDMI_PACKET_NULL, 0, 0); +} + +void hdmi_tx_general_control_packet(int mute) +{ + unsigned char buf[7]; + memset(buf, 0x0, 7); + buf[0] = (mute) ? 0x01 : 0x10; + buf[1] = HDMI_COLOR_DEPTH_24 | (HDMI_PHASE_4 << 4); + hdmi_write_packet(HDMI_PACKET_GENERAL_CTRL, buf, 7); +} + +int hdmi_get_pic_aspect(enum hdmi_video_code_t vic) +{ + switch (vic) { + case HDMI_640x480p60_4x3: + case HDMI_720x480p60_4x3: + case HDMI_1440x480i60_4x3: + case HDMI_1440x240p60_4x3: + case HDMI_2880x480i60_4x3: + case HDMI_2880x240p60_4x3: + case HDMI_1440x480p60_4x3: + case HDMI_720x576p50_4x3: + case HDMI_1440x576i50_4x3: + case HDMI_1440x288p50_4x3: + case HDMI_2880x576i50_4x3: + case HDMI_2880x288p50_4x3: + case HDMI_1440x576p50_4x3: + return HDMI_PIC_ASPECT_4_3; + default: + break; + } + return HDMI_PIC_ASPECT_16_9; +} + +int hdmi_get_vic(int resx, int resy, int fps, int interlace) +{ + struct hdmi_vic_t info; + int i; + + info.resx = resx; + info.resy = resy; + info.freq = fps; + info.option = (interlace) ? HDMI_VIC_INTERLACE : HDMI_VIC_PROGRESS; + info.option |= (vout_check_ratio_16_9(resx, resy)) ? + HDMI_VIC_16x9 : HDMI_VIC_4x3; + for (i = 0; i < HDMI_VIDEO_CODE_MAX; i++) { + if (memcmp(&hdmi_vic_info[i], &info, + sizeof(struct hdmi_vic_t)) == 0) + return i; + } + return HDMI_UNKNOW; +} + +void hdmi_tx_avi_infoframe_packet(vdo_color_fmt colfmt, + enum hdmi_video_code_t vic) +{ + unsigned int header; + unsigned char buf[28]; + unsigned char temp; + + memset(buf, 0x0, 28); + header = HDMI_PACKET_INFOFRAME_AVI + (0x2 << 8) + (0x0d << 16); + buf[1] = HDMI_SI_NO_DATA + (HDMI_BI_V_H_VALID << 2) + + (HDMI_AF_INFO_NO_DATA << 4); + switch (colfmt) { + case VDO_COL_FMT_YUV422H: + case VDO_COL_FMT_YUV422V: + temp = HDMI_OUTPUT_YUV422; + break; + case VDO_COL_FMT_YUV444: + temp = HDMI_OUTPUT_YUV444; + break; + case VDO_COL_FMT_ARGB: + default: + temp = HDMI_OUTPUT_RGB; + break; + } + buf[1] += (temp << 5); + buf[2] = HDMI_ASPECT_RATIO_PIC + (hdmi_get_pic_aspect(vic) << 4) + + (HDMI_COLORIMETRY_ITU709 << 6); + buf[3] = 0x84; + buf[4] = vic; + switch (vic) { + case HDMI_1440x480i60_16x9: + case HDMI_1440x576i50_16x9: + buf[5] = HDMI_PIXEL_REP_2; + break; + default: + buf[5] = HDMI_PIXEL_REP_NO; + break; + } + buf[0] = hdmi_checksum((unsigned char *)&header, buf, 28); + hdmi_write_packet(header, buf, 28); +} + +void hdmi_tx_audio_infoframe_packet(int channel, int freq) +{ + unsigned int header; + unsigned char buf[28]; + + memset(buf, 0x0, 28); + header = HDMI_PACKET_INFOFRAME_AUDIO + (0x1 << 8) + (0x0a << 16); + buf[1] = (channel - 1) + (HDMI_AUD_TYPE_REF_STM << 4); + buf[2] = 0x0; /* HDMI_AUD_SAMPLE_24 + (freq << 2); */ + buf[3] = 0x00; + /* 0x13: RRC RLC RR RL FC LFE FR FL + 0x1F: FRC FLC RR RL FC LFE FR FL */ + buf[4] = (channel == 8) ? 0x13 : 0; + buf[5] = 0x0; /* 0 db */ + buf[0] = hdmi_checksum((unsigned char *)&header, buf, 28); + hdmi_write_packet(header, buf, 28); +} + +void hdmi_tx_vendor_specific_infoframe_packet(void) +{ + unsigned int header; + unsigned char buf[28]; + unsigned char structure_3d, meta_present; + unsigned char hdmi_video_format; + + /* 0-No,1-1 byte param,2-3D format */ + hdmi_video_format = (g_vpp.hdmi_3d_type) ? 2 : 0; + /* HDMI_3D_STRUCTURE_XXX; */ + structure_3d = (g_vpp.hdmi_3d_type == 1) ? 0 : g_vpp.hdmi_3d_type; + meta_present = 0; + + memset(buf, 0x0, 28); + header = HDMI_PACKET_INFOFRAME_VENDOR + (0x1 << 8) + (0xa << 16); + buf[1] = 0x3; + buf[2] = 0xC; + buf[3] = 0x0; + buf[4] = (hdmi_video_format << 5); + buf[5] = (structure_3d << 4) + ((meta_present) ? 0x8 : 0x0); + buf[6] = 0x0; /* 3D_Ext_Data */ +#if 0 /* metadata present */ + buf[7] = 0x0; /* 3D_Metadata_type,3D_Metadata_Length(N) */ + buf[8] = 0x0; /* 3D Metadata 1_N */ +#endif + buf[0] = hdmi_checksum((unsigned char *)&header, buf, 28); + hdmi_write_packet(header, buf, 28); +} + +#define HDMI_N_CTS_USE_TABLE +#ifdef HDMI_N_CTS_USE_TABLE +struct hdmi_n_cts_s { + unsigned int n; + unsigned int cts; +}; + +struct hdmi_n_cts_s hdmi_n_cts_table[7][11] = { + /* 32kHz */ + {{ 9152, 84375 }, {4096, 37800}, {4096, 40500}, {8192, 81081}, + { 4096, 81000 }, {4096, 81081}, {11648, 316406}, {4096, 111375}, + { 11648, 632812}, {4096, 222750}, {4096, 0}}, + /* 44.1kHz */ + {{7007, 46875}, {6272, 42000}, {6272, 45000}, {6272, 45045}, + {6272, 90000}, {6272, 90090}, {17836, 351562}, {6272, 123750}, + {17836, 703125}, {6272, 247500}, {6272, 0}}, + /* 88.2kHz */ + {{14014, 46875}, {12544, 42000}, {12544, 45000}, {12544, 45045}, + {12544, 90000}, {12544, 90090}, {35672, 351562}, {12544, 123750}, + {35672, 703125}, {12544, 247500}, {12544, 0}}, + /* 176.4kHz */ + {{28028, 46875}, {25088, 42000}, {25088, 45000}, {25088, 45045}, + {25088, 90000}, {25088, 90090}, {71344, 351562}, {25088, 123750}, + {71344, 703125}, {25088, 247500}, {25088, 0}}, + /* 48kHz */ + {{9152, 56250}, {6144, 37800}, {6144, 40500}, {8192, 54054}, + {6144, 81000}, {6144, 81081}, {11648, 210937}, {6144, 111375}, + {11648, 421875}, {6144, 222750}, {6144, 0}}, + /* 96kHz */ + {{18304, 56250}, {12288, 37800}, {12288, 40500}, {16384, 54054}, + {12288, 81000}, {12288,81081}, {23296, 210937}, {12288, 111375}, + {23296, 421875}, {12288, 222750}, {12288, 0}}, + /* 192kHz */ + {{36608, 56250}, {24576, 37800}, {24576, 40500}, {32768, 54054}, + {24576, 81000}, {24576, 81081}, {46592, 210937}, {24576, 111375}, + {46592, 421875}, {24576, 222750}, {24576, 0}} +}; + +struct hdmi_n_cts_s *hdmi_get_n_cts(unsigned int tmds_clk, + unsigned int freq) +{ + int i, j; + + switch (freq) { + case 32000: + i = 0; + break; + case 44100: + i = 1; + break; + case 88200: + i = 2; + break; + case 176400: + i = 3; + break; + case 48000: + i = 4; + break; + case 96000: + i = 5; + break; + case 192000: + i = 6; + break; + default: + return 0; + } + + switch (tmds_clk) { + case 25174825: + j = 0; + break; + case 25200000: + j = 1; + break; + case 27000000: + j = 2; + break; + case 27027000: + j = 3; + break; + case 54000000: + j = 4; + break; + case 54054000: + j = 5; + break; + case 74175824: + j = 6; + break; + case 74250000: + j = 7; + break; + case 148351648: + j = 8; + break; + case 148500000: + j = 9; + break; + default: + j = 10; + break; + } + return &hdmi_n_cts_table[i][j]; +} +#endif + +void hdmi_set_audio_n_cts(unsigned int freq) +{ + unsigned int n = 0, cts = 0; + +#ifdef HDMI_N_CTS_USE_TABLE + struct hdmi_n_cts_s *p; + + p = hdmi_get_n_cts(g_vpp.hdmi_pixel_clock, freq); + if (p) { + n = p->n; + cts = p->cts; + MSG("[HDMI] use table n %d, cts %d\n", n, cts); + } +#endif + + if (n == 0) + n = 128 * freq / 1000; + + if (cts == 0) { +#ifdef __KERNEL__ + unsigned int tmp; + unsigned int pll_clk; + + pll_clk = auto_pll_divisor(DEV_I2S, GET_FREQ, 0, 0); + tmp = (inl(AUDREGF_BASE_ADDR + 0x70) & 0xF); + + switch (tmp) { + case 0 ... 4: + tmp = 0x01 << tmp; + break; + case 9 ... 12: + tmp = 3 * (0x1 << (tmp-9)); + break; + default: + tmp = 1; + break; + } + { + unsigned long long tmp2; + unsigned long long div2; + unsigned long mod; + + tmp2 = g_vpp.hdmi_pixel_clock; + tmp2 = tmp2 * n * tmp; + div2 = pll_clk; + mod = do_div(tmp2, div2); + cts = tmp2; + } + DBGMSG("[HDMI] i2s %d,cts %d,reg 0x%x\n", pll_clk, cts, + vppif_reg32_in(AUDREGF_BASE_ADDR + 0x70)); +#else + cts = (g_vpp.hdmi_pixel_clock / 1000) - 1; +#endif + } + hdmi_regs1->aud_sample_rate1.b.n_20bits = n; + hdmi_regs1->aud_ratio.b.acr_ratio = cts - 1; + hdmi_regs1->aud_sample_rate2.b.cts_select = 0; + cts = 0; + hdmi_regs1->aud_sample_rate1.b.cts_low_12bits = cts & 0xFFF; + hdmi_regs1->aud_sample_rate2.b.cts_hi_8bits = (cts & 0xFF000) >> 12; + DBGMSG("[HDMI] set audio freq %d,n %d,cts %d,tmds %d\n", + freq, n, cts, g_vpp.hdmi_pixel_clock); +} + +void hdmi_config_audio(struct vout_audio_t *info) +{ + unsigned int freq; + + g_vpp.hdmi_audio_channel = info->channel; + g_vpp.hdmi_audio_freq = info->sample_rate; + + /* enable ARF & ARFP clock */ + REG32_VAL(PM_CTRL_BASE_ADDR + 0x254) |= (BIT4 | BIT3); + hdmi_tx_audio_infoframe_packet(info->channel, info->sample_rate); + hdmi_audio_enable(VPP_FLAG_DISABLE); + hdmi_regs1->aud_mode.b.layout = (info->channel > 2) ? 1 : 0; + hdmi_regs1->aud_mode.b._2ch_eco = (info->channel > 2) ? 0 : 1; + switch (info->sample_rate) { + case 32000: + freq = 0x3; + break; + case 44100: + freq = 0x0; + break; + case 88200: + freq = 0x8; + break; + case 176400: + freq = 0xC; + break; + default: + case 48000: + freq = 0x2; + break; + case 96000: + freq = 0xA; + break; + case 192000: + freq = 0xE; + break; + case 768000: + freq = 0x9; + break; + } + hdmi_regs1->aud_chan_status0 = (freq << 24) + 0x4; + hdmi_regs1->aud_chan_status1 = 0x0; + hdmi_regs1->aud_chan_status2 = 0xb; + hdmi_regs1->aud_chan_status3 = 0x0; + hdmi_regs1->aud_chan_status4 = 0x0; + hdmi_regs1->aud_chan_status5 = 0x0; + + hdmi_set_audio_n_cts(info->sample_rate); + hdmi_regs1->aud_ratio.b.acr_enable = 1; + hdmi_regs1->aud_sample_rate2.b.aipclk_rate = 0; + hdmi_audio_enable(VPP_FLAG_ENABLE); +} + +void hdmi_config_video(struct hdmi_info_t *info) +{ + hdmi_set_output_colfmt(info->outfmt); + hdmi_tx_avi_infoframe_packet(info->outfmt, info->vic); + hdmi_tx_vendor_specific_infoframe_packet(); +} + +void hdmi_set_option(unsigned int option) +{ + vdo_color_fmt colfmt; + int temp; + + hdmi_set_dvi_enable((option & EDID_OPT_HDMI) ? + VPP_FLAG_DISABLE : VPP_FLAG_ENABLE); + hdmi_audio_enable((option & EDID_OPT_AUDIO) ? + VPP_FLAG_ENABLE : VPP_FLAG_DISABLE); + + colfmt = hdmi_get_output_colfmt(); + switch (colfmt) { + case VDO_COL_FMT_YUV422H: + temp = option & EDID_OPT_YUV422; + break; + case VDO_COL_FMT_YUV444: + temp = option & EDID_OPT_YUV444; + break; + default: + temp = 1; + break; + } + if (temp == 0) { + hdmi_set_output_colfmt(VDO_COL_FMT_ARGB); + DBG_MSG("[HDMI] TV not support %s,use default RGB\n", + vpp_colfmt_str[colfmt]); + } + DBG_MSG("[HDMI] set option(8-HDMI,6-AUDIO) 0x%x\n", option); +} + +void hdmi_config(struct hdmi_info_t *info) +{ + struct vout_audio_t audio_info; + int h_porch; + int delay_cfg; + vpp_clock_t clock; + + hdmi_regs1->ctrl.b.hden = 0; + hdmi_regs1->infoframe_ctrl.b.select = 0; + hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 0; + hdmi_config_video(info); + + govrh_get_tg(p_govrh, &clock); + h_porch = clock.total_pixel_of_line - clock.end_pixel_of_active; /*fp*/ + delay_cfg = 47 - h_porch; + if (delay_cfg <= 0) + delay_cfg = 1; + h_porch = clock.begin_pixel_of_active; /* bp */ + h_porch = (h_porch - (delay_cfg + 1) - 26) / 32; + if (h_porch <= 0) + h_porch = 1; + if (h_porch >= 8) + h_porch = 0; + + hdmi_regs1->general_ctrl.b.cp_delay = delay_cfg; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */ + hdmi_regs1->infoframe_ctrl.b.horiz_blank_max_pck = h_porch; + DBGMSG("[HDMI] H blank max pck %d,delay %d\n", h_porch, delay_cfg); + + audio_info.fmt = 16; + audio_info.channel = info->channel; + audio_info.sample_rate = info->freq; + hdmi_config_audio(&audio_info); + + hdmi_regs1->infoframe_ctrl.b.fifo1_addr = 0; + hdmi_regs1->infoframe_ctrl.b.fifo1_len = 2; + hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 1; + hdmi_set_option(info->option); + hdmi_regs2->test.b.tre_en = + (g_vpp.hdmi_pixel_clock < 40000000) ? 3 : 2; +} + +/*----------------------- Module API --------------------------------------*/ +void hdmi_set_cp_enable(vpp_flag_t enable) +{ + if (!g_vpp.hdmi_cp_enable) + enable = 0; + + if (hdmi_cp) + hdmi_cp->enable(enable); + +#ifdef __KERNEL__ + if (hdmi_cp && hdmi_cp->poll) { + vpp_irqproc_del_work(VPP_INT_GOVRH_VBIS, (void *)hdmi_cp->poll); + if (enable) + vpp_irqproc_work(VPP_INT_GOVRH_VBIS, + (void *)hdmi_cp->poll, 0, 0, 0); + } +#endif +} + +int hdmi_check_cp_int(void) +{ + int ret = 0; + + if (hdmi_cp) + ret = hdmi_cp->interrupt(); + return ret; +} + +void hdmi_get_bksv(unsigned int *bksv) +{ + if (hdmi_cp) + hdmi_cp->get_bksv(bksv); +} + +#ifdef __KERNEL__ +void hdmi_hotplug_notify(int plug_status) +{ + if (g_vpp.hdmi_disable) + return; + vpp_netlink_notify_plug(VPP_VOUT_NUM_HDMI, plug_status); +} +#else +#define hdmi_hotplug_notify +#endif + +int hdmi_check_plugin(int hotplug) +{ + static int last_plugin = -1; + int plugin; + int flag; + + if (g_vpp.hdmi_disable) + return 0; + + plugin = hdmi_get_plugin(); + hdmi_clear_plug_status(); +#ifdef __KERNEL__ + /* disable HDMI before change clock */ + if (plugin == 0) { + hdmi_set_enable(0); + hdmi_set_power_down(1); + } + vpp_set_clock_enable(DEV_HDMII2C, plugin, 1); + vpp_set_clock_enable(DEV_HDCE, plugin, 1); + + /* slow down clock for plugout */ + flag = (auto_pll_divisor(DEV_HDMILVDS, GET_FREQ, 0, 0) + == 8000000) ? 0 : 1; + if ((plugin != flag) && !g_vpp.virtual_display) { + int pixclk; + + pixclk = (plugin) ? g_vpp.hdmi_pixel_clock : 8000000; + auto_pll_divisor(DEV_HDMILVDS, SET_PLLDIV, 0, pixclk); + } +#endif + if (last_plugin != plugin) { + DPRINT("[HDMI] HDMI plug%s,hotplug %d\n", (plugin) ? + "in" : "out", hotplug); + last_plugin = plugin; + } +#if 0 /* Denzel test */ + if (plugin == 0) + hdmi_set_dvi_enable(VPP_FLAG_ENABLE); +#endif + return plugin; +} + +void hdmi_reg_dump(void) +{ + DPRINT("========== HDMI register dump ==========\n"); + vpp_reg_dump(REG_HDMI_BEGIN, REG_HDMI_END - REG_HDMI_BEGIN); + vpp_reg_dump(REG_HDMI2_BEGIN, REG_HDMI2_END - REG_HDMI2_BEGIN); + + DPRINT("---------- HDMI common ----------\n"); + DPRINT("enable %d,hden %d,reset %d,dvi %d\n", + hdmi_regs1->general_ctrl.b.enable, + hdmi_regs1->ctrl.b.hden, + hdmi_regs1->general_ctrl.b.reset, + hdmi_regs1->general_ctrl.b.dvi_mode_enable); + DPRINT("colfmt %d,conv 422 %d,hsync low %d,vsync low %d\n", + hdmi_regs1->general_ctrl.b.output_format, + hdmi_regs1->general_ctrl.b.convert_yuv422, + hdmi_regs1->general_ctrl.b.hsync_low_active, + hdmi_regs1->general_ctrl.b.vsync_low_active); + DPRINT("dbg bus sel %d,state mach %d\n", + hdmi_regs1->general_ctrl.b.dbg_bus_select, + hdmi_regs1->general_ctrl.b.state_machine_status); + DPRINT("eep reset %d,encode %d,eess %d\n", + hdmi_regs1->ctrl.b.eeprom_reset, + hdmi_regs1->ctrl.b.encode_enable, + hdmi_regs1->ctrl.b.eess_enable); + DPRINT("verify pj %d,auth test %d,cipher %d\n", + hdmi_regs1->ctrl.b.verify_pj_enable, + hdmi_regs1->ctrl.b.auth_test_key, + hdmi_regs1->ctrl.b.cipher_1_1); + DPRINT("preamble %d\n", hdmi_regs1->ctrl.b.preamble); + + DPRINT("---------- HDMI hotplug ----------\n"); + DPRINT("plug %s\n", (hdmi_regs1->hotplug_detect.b.sts) ? "in" : "out"); + DPRINT("plug in enable %d, status %d\n", + hdmi_regs1->hotplug_detect.b.in_enable, + hdmi_regs1->hotplug_detect.b.in_sts); + DPRINT("plug out enable %d, status %d\n", + hdmi_regs1->hotplug_detect.b.out_enable, + hdmi_regs1->hotplug_detect.b.out_sts); + DPRINT("debounce detect %d,sample %d\n", + hdmi_regs1->hotplug_debounce.b.detect, + hdmi_regs1->hotplug_debounce.b.sample); + + DPRINT("---------- I2C ----------\n"); + DPRINT("enable %d,exit FSM %d,key read %d\n", + hdmi_regs1->ctrl.b.i2c_enable, + hdmi_regs1->i2c_ctrl.b.force_exit_fsm, + hdmi_regs1->i2c_ctrl.b.key_read_word); + DPRINT("clk divid %d,rd data 0x%x,wr data 0x%x\n", + hdmi_regs1->i2c_ctrl.b.i2c_clk_divider, + hdmi_regs1->i2c_ctrl2.b.rd_data, + hdmi_regs1->i2c_ctrl2.b.wr_data); + DPRINT("start %d,stop %d,wr avail %d\n", + hdmi_regs1->i2c_ctrl2.b.sw_start_req, + hdmi_regs1->i2c_ctrl2.b.sw_stop_req, + hdmi_regs1->i2c_ctrl2.b.wr_data_avail); + DPRINT("status %d,sw read %d,sw i2c req %d\n", + hdmi_regs1->i2c_ctrl2.b.i2c_status, + hdmi_regs1->i2c_ctrl2.b.sw_read, + hdmi_regs1->i2c_ctrl2.b.sw_i2c_req); + + DPRINT("---------- AUDIO ----------\n"); + DPRINT("enable %d,sub pck %d,spflat %d\n", + hdmi_regs1->aud_enable, + hdmi_regs1->aud_mode.b.sub_packet, + hdmi_regs1->aud_mode.b.spflat); + DPRINT("aud pck insert reset %d,enable %d,delay %d\n", + hdmi_regs1->aud_insert_ctrl.b.pck_insert_reset, + hdmi_regs1->aud_insert_ctrl.b.pck_insert_enable, + hdmi_regs1->aud_insert_ctrl.b.insert_delay); + DPRINT("avmute set %d,clr %d,pixel repete %d\n", + hdmi_regs1->aud_insert_ctrl.b.avmute_set_enable, + hdmi_regs1->aud_insert_ctrl.b.avmute_clr_enable, + hdmi_regs1->aud_insert_ctrl.b.pixel_repetition); + DPRINT("acr ratio %d,acr enable %d,mute %d\n", + hdmi_regs1->aud_ratio.b.acr_ratio, + hdmi_regs1->aud_ratio.b.acr_enable, + hdmi_regs1->aud_ratio.b.mute); + DPRINT("layout %d,pwr save %d,n 20bits %d\n", + hdmi_regs1->aud_mode.b.layout, + hdmi_regs1->aud_mode.b.pwr_saving, + hdmi_regs1->aud_sample_rate1.b.n_20bits); + DPRINT("cts low 12 %d,hi 8 %d,cts sel %d\n", + hdmi_regs1->aud_sample_rate1.b.cts_low_12bits, + hdmi_regs1->aud_sample_rate2.b.cts_hi_8bits, + hdmi_regs1->aud_sample_rate2.b.cts_select); + DPRINT("aipclk rate %d\n", hdmi_regs1->aud_sample_rate2.b.aipclk_rate); + + DPRINT("---------- INFOFRAME ----------\n"); + DPRINT("sel %d,hor blank pck %d\n", + hdmi_regs1->infoframe_ctrl.b.select, + hdmi_regs1->infoframe_ctrl.b.horiz_blank_max_pck); + DPRINT("fifo1 ready %d,addr 0x%x,len %d\n", + hdmi_regs1->infoframe_ctrl.b.fifo1_rdy, + hdmi_regs1->infoframe_ctrl.b.fifo1_addr, + hdmi_regs1->infoframe_ctrl.b.fifo1_len); + DPRINT("fifo2 ready %d,addr 0x%x,len %d\n", + hdmi_regs1->infoframe_ctrl.b.fifo2_rdy, + hdmi_regs1->infoframe_ctrl.b.fifo2_addr, + hdmi_regs1->infoframe_ctrl.b.fifo2_len); + DPRINT("wr strobe %d,rd strobe %d,fifo addr %d\n", + hdmi_regs1->fifo_ctrl.b.wr_strobe, + hdmi_regs1->fifo_ctrl.b.rd_strobe, + hdmi_regs1->fifo_ctrl.b.addr); + + { + int i; + unsigned int buf[32]; + + for (i = 0; i <= hdmi_regs1->infoframe_ctrl.b.fifo1_len; i++) { + DPRINT("----- infoframe %d -----\n", i); + hdmi_read_fifo(i, buf, 32); + vpp_reg_dump((unsigned int) buf, 32); + } + } + + DPRINT("---------- HDMI test ----------\n"); + DPRINT("ch0 enable %d, data 0x%x\n", + hdmi_regs1->channel_test.b.ch0_enable, + hdmi_regs1->channel_test.b.ch0_data); + DPRINT("ch1 enable %d, data 0x%x\n", + hdmi_regs1->channel_test.b.ch1_enable, + hdmi_regs1->channel_test.b.ch1_data); + DPRINT("ch2 enable %d, data 0x%x\n", + hdmi_regs1->hotplug_detect.b.ch2_enable, + hdmi_regs1->hotplug_detect.b.ch2_data); + if (hdmi_cp) + hdmi_cp->dump(); +} + +#ifdef CONFIG_PM +static unsigned int *hdmi_pm_bk; +static unsigned int *hdmi_pm_bk2; +static unsigned int hdmi_pm_enable; +static unsigned int hdmi_pm_enable2; +static int hdmi_plug_enable = 0xFF; +static int hdmi_resume_plug_cnt; +#define HDMI_RESUME_PLUG_MS 50 +#define HDMI_RESUME_PLUG_CNT 20 +static void hdmi_do_resume_plug(struct work_struct *ptr) +{ + struct vout_t *vo; + int plugin; + struct delayed_work *dwork = to_delayed_work(ptr); + + plugin = hdmi_check_plugin(0); + vo = vout_get_entry(VPP_VOUT_NUM_HDMI); + vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin); + if (plugin) + hdmi_hotplug_notify(1); + hdmi_resume_plug_cnt--; + if (hdmi_resume_plug_cnt && (vpp_sdev.state == 0)) + schedule_delayed_work(dwork, + msecs_to_jiffies(HDMI_RESUME_PLUG_MS)); +} + +DECLARE_DELAYED_WORK(hdmi_resume_work, hdmi_do_resume_plug); + +void hdmi_suspend(int sts) +{ + vo_hdmi_set_clock(1); + switch (sts) { + case 0: /* disable module */ + cancel_delayed_work_sync(&hdmi_resume_work); + hdmi_pm_enable = hdmi_regs1->general_ctrl.b.enable; + hdmi_regs1->general_ctrl.b.enable = 0; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for wr only */ + hdmi_pm_enable2 = hdmi_regs1->ctrl.b.hden; + hdmi_regs1->ctrl.b.hden = 0; + if (hdmi_plug_enable == 0xFF) + hdmi_plug_enable = + hdmi_regs1->hotplug_detect.b.out_enable; + hdmi_enable_plugin(0); + break; + case 1: /* disable tg */ + break; + case 2: /* backup register */ + hdmi_pm_bk = vpp_backup_reg(REG_HDMI_BEGIN, + (REG_HDMI_END - REG_HDMI_BEGIN)); + hdmi_pm_bk2 = vpp_backup_reg(REG_HDMI2_BEGIN, + (REG_HDMI2_END - REG_HDMI2_BEGIN)); + hdmi_resume_plug_cnt = 20; + break; + default: + break; + } + vo_hdmi_set_clock(0); +} + +void hdmi_resume(int sts) +{ + vo_hdmi_set_clock(1); + switch (sts) { + case 0: /* restore register */ + switch_set_state(&vpp_sdev, 0); + vpp_restore_reg(REG_HDMI_BEGIN, + (REG_HDMI_END - REG_HDMI_BEGIN), hdmi_pm_bk); + vpp_restore_reg(REG_HDMI2_BEGIN, + (REG_HDMI2_END - REG_HDMI2_BEGIN), hdmi_pm_bk2); + hdmi_pm_bk = 0; + hdmi_pm_bk2 = 0; + hdmi_config(&hdmi_info); /* re-config HDMI info frame */ + if (g_vpp.hdmi_cp_p && hdmi_cp) + hdmi_cp->init(); + break; + case 1: /* enable module */ + hdmi_regs1->general_ctrl.b.enable = hdmi_pm_enable; + hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for wr only */ + hdmi_regs1->ctrl.b.hden = hdmi_pm_enable2; + break; + case 2: /* enable tg */ + hdmi_check_plugin(0); + hdmi_clear_plug_status(); + hdmi_enable_plugin(hdmi_plug_enable); + hdmi_plug_enable = 0xFF; + if (vpp_sdev.state == 0) { + hdmi_resume_plug_cnt = HDMI_RESUME_PLUG_CNT; + schedule_delayed_work(&hdmi_resume_work, + msecs_to_jiffies(HDMI_RESUME_PLUG_MS)); + } + break; + default: + break; + } + vo_hdmi_set_clock(0); +} +#else +#define hdmi_suspend NULL +#define hdmi_resume NULL +#endif + +void hdmi_init(void) +{ + struct fb_videomode vmode; + + g_vpp.hdmi_pixel_clock = vpp_get_base_clock(VPP_MOD_GOVRH); + g_vpp.hdmi_i2c_freq = HDMI_I2C_FREQ; + g_vpp.hdmi_i2c_udelay = 0; + g_vpp.hdmi_ctrl = 0x1000000; + g_vpp.hdmi_audio_pb4 = 0x0; + g_vpp.hdmi_audio_pb1 = 0x0; + + hdmi_info.outfmt = hdmi_get_output_colfmt(); + govrh_get_videomode(p_govrh, &vmode); + hdmi_info.vic = hdmi_get_vic(vmode.xres, vmode.yres, vmode.refresh, + (vmode.vmode & FB_VMODE_INTERLACED) ? 1 : 0); + hdmi_info.channel = 2; + hdmi_info.freq = 48000; + hdmi_info.option = EDID_OPT_AUDIO + EDID_OPT_HDMI; + + hdmi_enable_plugin(0); + + if (g_vpp.govrh_preinit) { + DBGMSG("[HDMI] hdmi_init for uboot logo\n"); + } else { + /* bit8-HDMI SDA,bit9-HDMI SCL,bit10-Hotplug,bit26-CEC */ + /* GPIO disable GPIO function */ + vppif_reg32_write(GPIO_BASE_ADDR+0x54, 0x4000700, 0, 0); + /* GPIO4 disable GPIO out */ + vppif_reg32_write(GPIO_BASE_ADDR+0x494, 0x4000700, 0, 0); +#if 0 + /* Suspend GPIO output enable */ + vppif_reg32_write(GPIO_BASE_ADDR+0x80, BIT23, 23, 1); + /* Suspend GPIO output high */ + vppif_reg32_write(GPIO_BASE_ADDR+0xC0, BIT23, 23, 1); + /* Wake3 disable pull ctrl */ + vppif_reg32_write(GPIO_BASE_ADDR+0x480, BIT19, 19, 0); +#endif + hdmi_regs2->level.b.level = 1; + hdmi_regs2->level.b.update = 1; + hdmi_regs2->igs.b.ldi_shift_left = 1; + hdmi_regs2->status.val = 0x0008c000; + hdmi_regs2->test.val = 0x00450409; + hdmi_regs2->test2.val = 0x00005022; + hdmi_regs2->test3 = (g_vpp.hdmi_sp_mode) ? + 0x00010100 : 0x00000100; + hdmi_set_enable(VPP_FLAG_DISABLE); + hdmi_set_dvi_enable(VPP_FLAG_DISABLE); + hdmi_regs1->ctrl.b.cipher_1_1 = 0; + + hdmi_regs1->tmds_ctrl.b.infoframe_sram_enable = 1; + hdmi_regs1->infoframe_ctrl.b.select = 0; + hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 0; + + hdmi_regs1->hotplug_detect.val = 0x0; + hdmi_regs1->channel_test.val = 0x1; + + hdmi_DDC_reset(); + hdmi_DDC_set_freq(g_vpp.hdmi_i2c_freq); + hdmi_regs1->ctrl.b.i2c_enable = 1; + } + g_vpp.hdmi_init = 1; + if (hdmi_cp) + hdmi_cp->init(); +} +#endif /* WMT_FTBLK_HDMI */ diff --git a/common/wmt_display/hdmi.h b/common/wmt_display/hdmi.h new file mode 100755 index 0000000..13c8094 --- /dev/null +++ b/common/wmt_display/hdmi.h @@ -0,0 +1,352 @@ +/*++ + * linux/drivers/video/wmt/hdmi.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef HDMI_H +/* To assert that only one occurrence is included */ +#define HDMI_H +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ +#include "vpp.h" + +/* following is the C++ header */ +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* #define HDMI_XXXX 1 *//*Example*/ +#define CONFIG_HDMI_INTERRUPT +#define HDMI_PLUG_DELAY 300 /* plug stable delay ms */ +#define HDMI_CP_TIME 3 /* should more than 2 seconds */ + +enum hdmi_packet_type_t { + HDMI_PACKET_NULL = 0x0, + HDMI_PACKET_AUD_CLOCK_REGEN = 0x1, + HDMI_PACKET_AUD_SAMPLE = 0x2, + HDMI_PACKET_GENERAL_CTRL = 0x3, + HDMI_PACKET_ACP = 0x4, + HDMI_PACKET_ISRC1 = 0x5, + HDMI_PACKET_ISRC2 = 0x6, + HDMI_PACKET_AUD_ONE_BIT_SAMPLE = 0x7, + HDMI_PACKET_AUD_DST = 0x8, + HDMI_PACKET_AUD_HBR = 0x9, + HDMI_PACKET_GAMUT_METADATA = 0xA, + HDMI_PACKET_INFOFRAME_VENDOR = 0x81, + HDMI_PACKET_INFOFRAME_AVI = 0x82, + HDMI_PACKET_INFOFRAME_SRC_PRODUCT_DESC = 0x83, + HDMI_PACKET_INFOFRAME_AUDIO = 0x84, + HDMI_PACKET_INFOFRAME_MPEG_SOURCE = 0x85 +}; + +/* color depth (CD field) */ +#define HDMI_COLOR_DEPTH_24 0x4 +#define HDMI_COLOR_DEPTH_30 0x5 +#define HDMI_COLOR_DEPTH_36 0x6 +#define HDMI_COLOR_DEPTH_48 0x7 + +/* pixel packing phase (PP field) */ +#define HDMI_PHASE_4 0x0 +#define HDMI_PHASE_1 0x1 +#define HDMI_PHASE_2 0x2 +#define HDMI_PHASE_3 0x3 + +/* Scan Information (AVI InfoFrame S0/S1) */ +#define HDMI_SI_NO_DATA 0x0 +#define HDMI_SI_OVERSCAN 0x1 +#define HDMI_SI_UNDERSCAN 0x2 + +/* Bar Info (AVI InfoFrame B0/B1) */ +#define HDMI_BI_DATA_NOT_VALID 0x0 +#define HDMI_BI_VERT_VALID 0x1 +#define HDMI_BI_HORIZ_VALID 0x2 +#define HDMI_BI_V_H_VALID 0x3 + +/* Active Format Information Present (AVI InfoFrame A0) */ +#define HDMI_AF_INFO_NO_DATA 0x0 +#define HDMI_AF_INFO_PRESENT 0x1 + +/* RGB or YCbCr (AVI InfoFrame Y0/Y1) */ +#define HDMI_OUTPUT_RGB 0x0 +#define HDMI_OUTPUT_YUV422 0x1 +#define HDMI_OUTPUT_YUV444 0x2 + +/* Aspect Ratio (AVI InfoFrame R0/R1/R2/R3) */ +#define HDMI_ASPECT_RATIO_PIC 0x8 +#define HDMI_ASPECT_RATIO_4_3 0x9 +#define HDMI_ASPECT_RATIO_16_9 0xA +#define HDMI_ASPECT_RATIO_14_9 0xB + +/* Picture Aspect Ratio (AVI InfoFrame M0/M1) */ +#define HDMI_PIC_ASPECT_NO_DATA 0x0 +#define HDMI_PIC_ASPECT_4_3 0x1 +#define HDMI_PIC_ASPECT_16_9 0x2 + +/* Colorimetry (AVI InfoFrame C0/C1) */ +#define HDMI_COLORIMETRY_NO 0x0 +#define HDMI_COLORIMETRY_ITU601 0x1 +#define HDMI_COLORIMETRY_ITU709 0x2 + +/* Non-uniform Picture Scaling (AVI InfoFrame SC0/SC1) */ +#define HDMI_NUSCALE_NO 0x0 +#define HDMI_NUSCALE_HOR 0x1 +#define HDMI_NUSCALE_VERT 0x2 +#define HDMI_NUSCALE_HOR_VERT 0x3 + +/* Pixel Repetition (AVI InfoFrame PR0/PR1/PR2/PR3) */ +#define HDMI_PIXEL_REP_NO 0x0 +#define HDMI_PIXEL_REP_2 0x1 +#define HDMI_PIXEL_REP_3 0x2 +#define HDMI_PIXEL_REP_4 0x3 +#define HDMI_PIXEL_REP_5 0x4 +#define HDMI_PIXEL_REP_6 0x5 +#define HDMI_PIXEL_REP_7 0x6 +#define HDMI_PIXEL_REP_8 0x7 +#define HDMI_PIXEL_REP_9 0x8 +#define HDMI_PIXEL_REP_10 0x9 + +/* Video Code */ +enum hdmi_video_code_t { + HDMI_UNKNOW = 0, + HDMI_640x480p60_4x3, + HDMI_720x480p60_4x3, + HDMI_720x480p60_16x9, + HDMI_1280x720p60_16x9, + HDMI_1920x1080i60_16x9, + HDMI_1440x480i60_4x3, + HDMI_1440x480i60_16x9, + HDMI_1440x240p60_4x3, + HDMI_1440x240p60_16x9, + HDMI_2880x480i60_4x3, /* 10 */ + HDMI_2880x480i60_16x9, + HDMI_2880x240p60_4x3, + HDMI_2880x240p60_16x9, + HDMI_1440x480p60_4x3, + HDMI_1440x480p60_16x9, + HDMI_1920x1080p60_16x9, + HDMI_720x576p50_4x3, + HDMI_720x576p50_16x9, + HDMI_1280x720p50_16x9, + HDMI_1920x1080i50_16x9, /* 20 */ + HDMI_1440x576i50_4x3, + HDMI_1440x576i50_16x9, + HDMI_1440x288p50_4x3, + HDMI_1440x288p50_16x9, + HDMI_2880x576i50_4x3, + HDMI_2880x576i50_16x9, + HDMI_2880x288p50_4x3, + HDMI_2880x288p50_16x9, + HDMI_1440x576p50_4x3, + HDMI_1440x576p50_16x9, /* 30 */ + HDMI_1920x1080p50_16x9, + HDMI_1920x1080p24_16x9, + HDMI_1920x1080p25_16x9, + HDMI_1920x1080p30_16x9, + HDMI_VIDEO_CODE_MAX +}; + +/* Audio Channel Count (Audio InfoFrame CC0/CC1/CC2) */ +enum hdmi_audio_channel_count_t { + HDMI_AUD_CHAN_REF_STM = 0, + HDMI_AUD_CHAN_2CH, + HDMI_AUD_CHAN_3CH, + HDMI_AUD_CHAN_4CH, + HDMI_AUD_CHAN_5CH, + HDMI_AUD_CHAN_6CH, + HDMI_AUD_CHAN_7CH, + HDMI_AUD_CHAN_8CH +}; + +/* Audio Coding type (Audio InfoFrame CT0/CT1/CT2/CT3) */ +#define HDMI_AUD_TYPE_REF_STM 0x0 +#define HDMI_AUD_TYPE_PCM 0x1 +#define HDMI_AUD_TYPE_AC3 0x2 +#define HDMI_AUD_TYPE_MPEG1 0x3 +#define HDMI_AUD_TYPE_MP3 0x4 +#define HDMI_AUD_TYPE_MPEG2 0x5 +#define HDMI_AUD_TYPE_AAC 0x6 +#define HDMI_AUD_TYPE_DTS 0x7 +#define HDMI_AUD_TYPE_ATRAC 0x8 + +/* Audio Sample size (Audio InfoFrame SS0/SS1) */ +#define HDMI_AUD_SAMPLE_REF_STM 0x0 +#define HDMI_AUD_SAMPLE_16 0x1 +#define HDMI_AUD_SAMPLE_20 0x2 +#define HDMI_AUD_SAMPLE_24 0x3 + +/* Audio Sample frequency (Audio InfoFrame SF0/SF1/SF2) */ +#define HDMI_AUD_FREQ_REF_STM 0x0 +#define HDMI_AUD_FREQ_32K 0x1 +#define HDMI_AUD_FREQ_44_1K 0x2 +#define HDMI_AUD_FREQ_48K 0x3 +#define HDMI_AUD_FREQ_88_2K 0x4 +#define HDMI_AUD_FREQ_96K 0x5 +#define HDMI_AUD_FREQ_176_4K 0x6 +#define HDMI_AUD_FREQ_192K 0x7 + +/* 3D_Structure */ +#define HDMI_3D_STRUCTURE_FRAME_PACKING 0x0 +#define HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE 0x1 +#define HDMI_3D_STRUCTURE_LINE_ALTERNATIVE 0x2 +#define HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL 0x3 +#define HDMI_3D_STRUCTURE_L_DEPTH 0x4 +#define HDMI_3D_STRUCTURE_L_DEP_GRA_GDEP 0x5 +#define HDMI_3D_STRUCTURE_TOP_AND_BOTTOM 0x6 +#define HDMI_3D_STRUCTURE_SIZE_BY_SIZE_HALF 0x8 + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void hdmi_xxx_t; *//*Example*/ +struct hdmi_info_t { + /* video */ + vdo_color_fmt outfmt; + int vic; + + /* audio */ + int channel; + int freq; + + /* option */ + int option; + +}; + +#define HDMI_VIC_INTERLACE BIT(0) +#define HDMI_VIC_PROGRESS 0 +#define HDMI_VIC_4x3 BIT(1) +#define HDMI_VIC_16x9 0 + +struct hdmi_vic_t { + unsigned short resx; + unsigned short resy; + char freq; + char option; +}; + +struct hdmi_cp_t { + void (*init)(void); + void (*enable)(int on); + int (*poll)(void); + void (*dump)(void); + int (*interrupt)(void); + void (*get_bksv)(unsigned int *bksv); +}; + +/*-------------------- EXPORTED PRIVATE VARIABLES ---------------------------*/ +#ifdef VPP_C +#define EXTERN + +const struct hdmi_vic_t hdmi_vic_info[HDMI_VIDEO_CODE_MAX] = { + { 0, 0, 0, 0 }, /* HDMI_UNKNOW = 0 */ + { 640, 480, 60, HDMI_VIC_4x3 }, /* HDMI_640x480p60_4x3 */ + { 720, 480, 60, HDMI_VIC_4x3 }, /* HDMI_720x480p60_4x3 */ + { 720, 480, 60, 0 }, /* HDMI_720x480p60_16x9 */ + { 1280, 720, 60, 0 }, /* HDMI_1280x720p60_16x9 */ + { 1920, 1080, 60, HDMI_VIC_INTERLACE }, /* HDMI_1920x1080i60_16x9 */ + { 720, 480, 60, HDMI_VIC_4x3 | HDMI_VIC_INTERLACE }, /*1440x480i60_4x3*/ + { 720, 480, 60, HDMI_VIC_INTERLACE }, /* HDMI_1440x480i60_16x9 */ + { 720, 240, 60, HDMI_VIC_4x3 }, /* HDMI_1440x240p60_4x3 */ + { 720, 240, 60, 0 }, /* HDMI_1440x240p60_16x9 */ + { 2880, 480, 60, HDMI_VIC_4x3 | HDMI_VIC_INTERLACE },/*2880x480i60_4x3*/ + { 2880, 480, 60, HDMI_VIC_INTERLACE }, /* HDMI_2880x480i60_16x9 */ + { 2880, 240, 60, HDMI_VIC_4x3 }, /* HDMI_2880x240p60_4x3 */ + { 2880, 240, 60, 0 }, /* HDMI_2880x240p60_16x9 */ + { 1440, 480, 60, HDMI_VIC_4x3 }, /* HDMI_1440x480p60_4x3 */ + { 1440, 480, 60, 0 }, /* HDMI_1440x480p60_16x9 */ + { 1920, 1080, 60, 0 }, /* HDMI_1920x1080p60_16x9 */ + { 720, 576, 50, HDMI_VIC_4x3 }, /* HDMI_720x576p50_4x3 */ + { 720, 576, 50, 0 }, /* HDMI_720x576p50_16x9 */ + { 1280, 720, 50, 0 }, /* HDMI_1280x720p50_16x9 */ + { 1920, 1080, 50, HDMI_VIC_INTERLACE }, /* HDMI_1920x1080i50_16x9, 20 */ + { 720, 576, 50, HDMI_VIC_INTERLACE | HDMI_VIC_4x3 }, /*1440x576i50_4x3*/ + { 720, 576, 50, HDMI_VIC_INTERLACE }, /* HDMI_1440x576i50_16x9 */ + { 720, 288, 50, HDMI_VIC_4x3 }, /* HDMI_1440x288p50_4x3 */ + { 720, 288, 50, 0 }, /* HDMI_1440x288p50_16x9 */ + { 2880, 576, 50, HDMI_VIC_INTERLACE | HDMI_VIC_4x3}, /*2880x576i50_4x3*/ + { 2880, 576, 50, HDMI_VIC_INTERLACE }, /* HDMI_2880x576i50_16x9 */ + { 2880, 288, 50, HDMI_VIC_4x3 }, /* HDMI_2880x288p50_4x3 */ + { 2880, 288, 50, 0 }, /* HDMI_2880x288p50_16x9 */ + { 1440, 576, 50, HDMI_VIC_4x3 }, /* HDMI_1440x576p50_4x3 */ + { 1440, 576, 50, 0 }, /* HDMI_1440x576p50_16x9, // 30 */ + { 1920, 1080, 50, 0 }, /* HDMI_1920x1080p50_16x9 */ + { 1920, 1080, 24, 0 }, /* HDMI_1920x1080p24_16x9 */ + { 1920, 1080, 25, 0 }, /* HDMI_1920x1080p25_16x9 */ + { 1920, 1080, 30, 0 } /* HDMI_1920x1080p30_16x9 */ +}; +#else +#define EXTERN extern + +EXTERN const struct hdmi_vic_t hdmi_vic_info[HDMI_VIDEO_CODE_MAX]; +#endif /* ifdef HDMI_C */ + +EXTERN struct hdmi_cp_t *hdmi_cp; +EXTERN int hdmi_ri_tm_cnt; +EXTERN struct hdmi_info_t hdmi_info; + +#ifdef VPP_C +EXPORT_SYMBOL(hdmi_cp); +EXPORT_SYMBOL(hdmi_ri_tm_cnt); +EXPORT_SYMBOL(hdmi_regs1); +EXPORT_SYMBOL(hdmi_regs2); +#endif + +/* EXTERN int hdmi_xxx; *//*Example*/ +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS -----------------------------*/ +/* #define HDMI_XXX_YYY xxxx *//*Example*/ +/*--------------------- EXPORTED PRIVATE FUNCTIONS -------------------------*/ +/* extern void hdmi_xxx(void); *//*Example*/ + +void hdmi_init(void); +void hdmi_reg_dump(void); +void hdmi_audio_enable(vpp_flag_t enable); +void hdmi_audio_mute(vpp_flag_t enable); +void hdmi_set_enable(vpp_flag_t enable); +void hdmi_set_avmute(vpp_flag_t mute); +void hdmi_set_dvi_enable(vpp_flag_t enable); +void hdmi_set_cp_enable(vpp_flag_t enable); +int hdmi_check_cp_int(void); +void hdmi_config(struct hdmi_info_t *info); +int hdmi_DDC_read(char addr, int index, char *buf, int length); +int hdmi_get_plugin(void); +int hdmi_get_plug_status(void); +void hdmi_clear_plug_status(void); +void hdmi_suspend(int sts); +void hdmi_resume(int sts); +void hdmi_set_power_down(int pwrdn); +void hdmi_enable_plugin(int enable); +vdo_color_fmt hdmi_get_output_colfmt(void); +void hdmi_set_sync_low_active(vpp_flag_t hsync, vpp_flag_t vsync); +void hdmi_get_sync_polar(int *hsync_hi, int *vsync_hi); +int hdmi_check_plugin(int hotplug); +void hdmi_set_cypher(int func); +void hdmi_set_option(unsigned int option); +void hdmi_get_bksv(unsigned int *bksv); +int hdmi_check_cp_dev_cnt(void); +void hdmi_hotplug_notify(int plug_status); +void hdmi_tx_vendor_specific_infoframe_packet(void); +int hdmi_get_vic(int resx, int resy, int fps, int interlace); + +#ifdef __cplusplus +} +#endif +#endif /* ifndef HDMI_H */ + diff --git a/common/wmt_display/hw/wmt-govrh-reg.h b/common/wmt_display/hw/wmt-govrh-reg.h new file mode 100755 index 0000000..ecdeb4f --- /dev/null +++ b/common/wmt_display/hw/wmt-govrh-reg.h @@ -0,0 +1,366 @@ +/*++ + * linux/drivers/video/wmt/hw/wmt-govrh-reg.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef WMT_GOVRH_REG_H +#define WMT_GOVRH_REG_H + +/* feature */ +#define WMT_FTBLK_GOVRH +#ifndef CONFIG_UBOOT +#define WMT_FTBLK_GOVRH_CURSOR +#endif +#define WMT_FTBLK_GOVRH2 + +#define GOVRH_FRAMEBUF_ALIGN 128 + +struct govrh_regs { + /* base1 */ + unsigned int cur_addr; /* 0x00 */ + unsigned int cur_width; + unsigned int cur_fb_width; + unsigned int cur_vcrop; + unsigned int cur_hcrop; /* 0x10 */ + union { + unsigned int val; + struct { + unsigned int start:11; + unsigned int reserved:5; + unsigned int end:11; + } b; + } cur_hcoord; /* 0x14 */ + + union { + unsigned int val; + struct { + unsigned int start:11; + unsigned int reserved:5; + unsigned int end:11; + } b; + } cur_vcoord; /* 0x18 */ + + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int reserved:7; + unsigned int out_field:1; /* 0:frame,1-field */ + } b; + } cur_status; /* 0x1C */ + + union { + unsigned int val; + struct { + unsigned int colkey:24; + unsigned int enable:1; + unsigned int invert:1; + unsigned int reserved:2; + unsigned int alpha:1; + } b; + } cur_color_key; /* 0x20 */ + + unsigned int reserved[3]; + + union { + unsigned int val; + struct { + unsigned int rgb:1; + unsigned int yuv422:1; + } b; + } dvo_pix; /* 0x30 */ + + union { + unsigned int val; + struct { + unsigned int delay:14; + unsigned int inv:1; + } b; + } dvo_dly_sel; /* 0x34 */ + + union { + unsigned int val; + struct { + unsigned int cur_enable:1; + unsigned int mem_enable:1; + unsigned int reserved:7; + unsigned int err_sts:1; + unsigned int reserved2:6; + unsigned int cur_sts:1; + unsigned int mem_sts:1; + } b; + } interrupt; /* 0x38 */ + + unsigned int dvo_blank_data; + unsigned int dirpath; /* 0x40 */ + union { + unsigned int val; + struct { + unsigned int v:8; + unsigned int u:8; + unsigned int y:8; + } b; + } saturation; /* 0x44 */ + + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int format:1; /* 0:YCbCr, 1:RGB */ + } b; + } saturation_enable; /* 0x48 */ + + unsigned int reserved2[13]; + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int reserved:7; + unsigned int h264:1; + } b; + } mif; /* 0x80 */ + + unsigned int colfmt; /* 0x84, 0:422,1:420 */ + unsigned int srcfmt; /* 0x88, 0:frame,1:field */ + unsigned int dstfmt; /* 0x8C, 0:frame,1:field */ + unsigned int ysa; /* 0x90 */ + unsigned int csa; + unsigned int pixwid; + unsigned int bufwid; + unsigned int vcrop; /* 0xA0 */ + unsigned int hcrop; + unsigned int fhi; + unsigned int colfmt2; /* 0xAC, 1-444,other refer 0x84 */ + unsigned int ysa2; /* 0xB0 */ + unsigned int csa2; + union { + unsigned int val; + struct { + unsigned int req_num:8; /* Y & RGB */ + unsigned int req_num_c:8; /* C */ + unsigned int frame_enable:1; + } b; + } mif_frame_mode; /* 0xB8 */ + + unsigned int reserved3[10]; + union { + unsigned int val; + struct { + unsigned int update:1; + unsigned int reserved:7; + unsigned int level:1; /* 0:level 1, 1:level2 */ + } b; + } sts; /* 0xE4 */ + + union { + unsigned int val; + struct { + unsigned int fixed:1; /* 0-top, 1-bottom */ + unsigned int enable:1; + } b; + } swfld; /* 0xE8 */ + + unsigned int reserved4[5]; + /* base2 */ + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int reserved:7; + unsigned int mode:1; /* 0-frame,1-field */ + } b; + } tg_enable; /* 0x100 */ + + unsigned int read_cyc; + unsigned int h_allpxl; + unsigned int v_allln; + unsigned int actln_bg; /* 0x110 */ + unsigned int actln_end; + unsigned int actpx_bg; + unsigned int actpx_end; + unsigned int vbie_line; /* 0x120 */ + unsigned int pvbi_line; + unsigned int hdmi_vbisw; + unsigned int hdmi_hsynw; + union { + unsigned int val; + struct { + unsigned int offset:12; + unsigned int reserved:4; + unsigned int field_invert:1; + } b; + } vsync_offset; /* 0x130 */ + + unsigned int field_status; /* 0x134, 1-BOTTOM,0-TOP */ + unsigned int reserved5[1]; /* 0x138 */ + union { + unsigned int val; + struct { + unsigned int mode:3; /* 011-frame packing progressive + format,111-frame packing interlace format */ + unsigned int inv_filed_polar:1; + unsigned int blank_value:16; + unsigned int reserved:11; + unsigned int addr_sel:1; /* in frame packing + interlace mode */ + } b; + } hdmi_3d; /* 0x13C */ + + unsigned int reserved5_2[2]; + union { + unsigned int val; + struct { + unsigned int outwidth:1; /* 0-24bit,1-12bit */ + unsigned int hsync_polar:1; /* 0-act high,1-act low */ + unsigned int enable:1; + unsigned int vsync_polar:1; /* 0-act high,1-act low */ + unsigned int reserved:4; + unsigned int rgb_swap:2; /* 0-RGB[7:0],1-RGB[0:7], + 2-BGR[7:0],3-BGR[0:7] */ + unsigned int reserved2:6; + unsigned int blk_dis:1; /* 0-Blank Data, + 1-Embeded sync CCIR656 */ + } b; + } dvo_set; /* 0x148 */ + + unsigned int reserved6; + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int reserved1:7; + unsigned int mode:1; + unsigned int reserved2:7; + unsigned int inversion:1; + } b; + } cb_enable; /* 0x150 */ + + unsigned int reserved7; + unsigned int h_allpxl2; + unsigned int v_allln2; + unsigned int actln_bg2; /* 0x160 */ + unsigned int actln_end2; + unsigned int actpx_bg2; + unsigned int actpx_end2; + unsigned int vbie_line2; /* 0x170 */ + unsigned int pvbi_line2; + unsigned int hdmi_vbisw2; + unsigned int hdmi_hsynw2; + union { + unsigned int val; + struct { + unsigned int outwidth:1; /* 0-24bit,1-12bit */ + unsigned int hsync_polar:1; /* 0-act high,1-act low */ + unsigned int enable:1; + unsigned int vsync_polar:1; /* 0-act high,1-act low */ + } b; + } lvds_ctrl; /* 0x180 */ + + union { + unsigned int val; + struct { + unsigned int pix:2; /* 0-YUV444,1-RGB,2-YUV422,3-RGB */ + } b; + } lvds_ctrl2; /* 0x184 */ + + unsigned int reserved_dac[12]; + + union { + unsigned int val; + struct { + unsigned int praf:8; + unsigned int pbaf:8; + unsigned int yaf:8; + } b; + } contrast; /* 0x1B8 */ + + unsigned int brightness; + unsigned int dmacsc_coef0; /* 0x1C0 */ + unsigned int dmacsc_coef1; + unsigned int dmacsc_coef2; + unsigned int dmacsc_coef3; + unsigned int dmacsc_coef4; /* 0x1D0 */ + unsigned int reserved8; + unsigned int dmacsc_coef5; + unsigned int dmacsc_coef6; + union { + unsigned int val; + struct { + unsigned int mode:1; /* 1: YUV2RGB, 0: RGB2YUV */ + unsigned int clamp:1; /* 0:Y,1:Y-16 */ + } b; + } csc_mode; /* 0x1E0 */ + + union { + unsigned int val; + struct { + unsigned int dvo:1; + unsigned int vga:1; + unsigned int reserved1:1; + unsigned int dac_clkinv:1; + unsigned int blank_zero:1; + unsigned int disp:1; + unsigned int lvds:1; + unsigned int hdmi:1; + unsigned int rgb_mode:2; /*0-YUV,1-RGB24,2-1555,3-565*/ + } b; + } yuv2rgb; /* 0x1E4 */ + + unsigned int h264_input_en; /* 0x1E8 */ + unsigned int reserved9; + unsigned int lvds_clkinv; /* 0x1F0 */ + unsigned int hscale_up; /* 0x1F4 */ + union { + unsigned int val; + struct { + unsigned int mode:3; /* 0:888,1:555,2:666,3:565,4:ori */ + unsigned int reserved:5; + unsigned int ldi:1; /* 0:shift right,1:shift left */ + } b; + } igs_mode; /* 0x1F8 */ + + union { + unsigned int val; + struct { + unsigned int mode:3; /* 0:888,1:555,2:666,3:565,4:ori */ + unsigned int reserved:5; + unsigned int ldi:1; /* 0:shift right,1:shift left */ + } b; + } igs_mode2; /* 0x1FC */ +}; + +/* GOVRH */ +#define REG_GOVRH_BASE1_BEGIN (GOVRH_BASE1_ADDR+0x00) +#define REG_GOVRH_YSA (GOVRH_BASE1_ADDR+0x90) +#define REG_GOVRH_CSA (GOVRH_BASE1_ADDR+0x94) +#define REG_GOVRH_BASE1_END (GOVRH_BASE1_ADDR+0xe8) +#define REG_GOVRH_BASE2_BEGIN (GOVRH_BASE2_ADDR+0x00) +#define REG_GOVRH_BASE2_END (GOVRH_BASE2_ADDR+0xFC) + +/* GOVRH2 */ +#define REG_GOVRH2_BASE1_BEGIN (GOVRH2_BASE1_ADDR+0x00) +#define REG_GOVRH2_YSA (GOVRH2_BASE1_ADDR+0x90) +#define REG_GOVRH2_CSA (GOVRH2_BASE1_ADDR+0x94) +#define REG_GOVRH2_BASE1_END (GOVRH2_BASE1_ADDR+0xe8) +#define REG_GOVRH2_BASE2_BEGIN (GOVRH2_BASE2_ADDR+0x00) +#define REG_GOVRH2_BASE2_END (GOVRH2_BASE2_ADDR+0xFC) + +#endif /* WMT_GOVRH_REG_H */ diff --git a/common/wmt_display/hw/wmt-hdmi-reg.h b/common/wmt_display/hw/wmt-hdmi-reg.h new file mode 100755 index 0000000..c065055 --- /dev/null +++ b/common/wmt_display/hw/wmt-hdmi-reg.h @@ -0,0 +1,379 @@ +/*++ + * linux/drivers/video/wmt/hw/wmt-hdmi-reg.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef WMT_HDMI_REG_H +#define WMT_HDMI_REG_H + +#define WMT_FTBLK_HDMI + +#define HDMI_BASE_ADDR (HDMI_TRANSMITTE_BASE_ADDR + 0xC000) + +struct hdmi_base1_regs { + unsigned int _100_11c[8]; + + union { + unsigned int val; + struct { + unsigned int eeprom_reset:1; + unsigned int encode_enable:1; + unsigned int hden:1; + unsigned int eess_enable:1; + unsigned int verify_pj_enable:1; + unsigned int i2c_enable:1; + unsigned int auth_test_key:1; + unsigned int _7:1; + unsigned int cipher_1_1:1; + unsigned int _9_11:3; + unsigned int preamble:4; + unsigned int _16_19:4; + unsigned int encode_window:3; + } b; + } ctrl; /* 0x120 */ + + union { + unsigned int val; + struct { + unsigned int _0_6:7; + unsigned int force_exit_fsm:1; + unsigned int key_read_word:7; + unsigned int i2c_sw_reset:1; + unsigned int i2c_clk_divider:16; + } b; + } i2c_ctrl; /* 0x124 */ + + union { + unsigned int val; + struct { + unsigned int wr_data:8; + unsigned int rd_data:8; + unsigned int sw_start_req:1; + unsigned int sw_stop_req:1; + unsigned int wr_data_avail:1; + unsigned int i2c_status:1; /* 0-not using,1-in using */ + unsigned int cp_key_req:1; + unsigned int cp_key_read:1; + unsigned int cp_key_last:1; + unsigned int _23:1; + unsigned int cp_src_sel:1; + unsigned int sw_read:1; + unsigned int sw_i2c_req:1; + unsigned int ksv_list_avail:1; + unsigned int ksv_verify_done:1; + } b; + } i2c_ctrl2; /* 0x128 */ + + unsigned int _12c_27c[85]; + + union { + unsigned int val; + struct { + unsigned int reset:1; + unsigned int enable:1; + unsigned int _2_5:4; + unsigned int dvi_mode_enable:1; + unsigned int output_format:2; /* 0-RGB, + 1-YUV444,2-YUV422 */ + unsigned int convert_yuv422:1; + unsigned int hsync_low_active:1; /* 0-active hi,1-lo */ + unsigned int dbg_bus_select:1; /* 0-before,1-after */ + unsigned int _12:1; + unsigned int vsync_low_active:1; /* 0-active hi,1-lo */ + unsigned int _14_15:2; + unsigned int cp_delay:7; + unsigned int _23:1; + unsigned int vsync_enable:3; /* write only */ + unsigned int state_machine_status:5; + } b; + } general_ctrl; /* 0x280 */ + + union { + unsigned int val; + struct { + unsigned int select:1; /* 0-fifo1,1-fifo2 */ + unsigned int fifo1_rdy:1; /* Info frame FIFO 1 ready */ + unsigned int fifo2_rdy:1; /* Info frame FIFO 2 ready */ + unsigned int _3:1; + unsigned int fifo1_addr:4; /* FIFO 1 start address */ + unsigned int fifo1_len:5; /* FIFO 1 length */ + unsigned int _13_15:3; + unsigned int fifo2_addr:4; /* FIFO 2 start address */ + unsigned int fifo2_len:5; /* FIFO 2 length */ + unsigned int _25_27:3; + unsigned int horiz_blank_max_pck:3; /* Max packets + that insert during HSYNC */ + } b; + } infoframe_ctrl; /* 0x284 */ + unsigned int _288_290[3]; + + union { + unsigned int val; + struct { + unsigned int pck_insert_reset:1; + unsigned int pck_insert_enable:1; + unsigned int avmute_set_enable:1; + unsigned int avmute_clr_enable:1; + unsigned int insert_delay:12; + unsigned int _16_29:14; + unsigned int pixel_repetition:2; /* 0-none,1-2x,2-4x */ + } b; + } aud_insert_ctrl; /* 0x294 */ + + unsigned int _298; + + union { + unsigned int val; + struct { + unsigned int _0_7:8; + unsigned int acr_ratio:20; + unsigned int acr_enable:1; + unsigned int mute:1; + } b; + } aud_ratio; /* 0x29c */ + + unsigned int aud_enable; /* 0x2a0 */ + unsigned int _2a4_2a8[2]; + + union { + unsigned int val; + struct { + unsigned int sub_packet:4; + unsigned int spflat:4; + unsigned int _2ch_eco:1; + unsigned int _9:1; + unsigned int layout:1; /* 0-2 channel,1-8 channel */ + unsigned int pwr_saving:1; /* 0-normal,1-power saving */ + } b; + } aud_mode; /* 0x2ac */ + + unsigned int _2b0_38c[56]; + unsigned int aud_chan_status0; /* 0x390 */ + unsigned int aud_chan_status1; /* 0x394 */ + unsigned int aud_chan_status2; /* 0x398 */ + unsigned int aud_chan_status3; /* 0x39c */ + unsigned int aud_chan_status4; /* 0x3a0 */ + unsigned int aud_chan_status5; /* 0x3a4 */ + + union { + unsigned int val; + struct { + unsigned int n_20bits:20; + unsigned int cts_low_12bits:12; + } b; + } aud_sample_rate1; /* 0x3a8 */ + + union { + unsigned int val; + struct { + unsigned int cts_hi_8bits:8; + unsigned int _8_27:20; + unsigned int aipclk_rate:2; /* 0-N/2,1-N,2-N/4,3-N*2 */ + unsigned int cts_select:1; /* 0-auto,1-fixed from reg */ + } b; + } aud_sample_rate2; /* 0x3ac */ + + unsigned int _3b0_3bc[4]; + unsigned int wr_fifo_addr[9]; /* 0x3c0 - 0x3e0 */ + + union { + unsigned int val; + struct { + unsigned int wr_strobe:1; + unsigned int rd_strobe:1; + unsigned int _2_7:6; + unsigned int addr:8; + } b; + } fifo_ctrl; /* 0x3e4 */ + + union { + unsigned int val; + struct { + unsigned int ch0_data:10; + unsigned int ch0_enable:1; + unsigned int _11_15:5; + unsigned int ch1_data:10; + unsigned int ch1_enable:1; + } b; + } channel_test; /* 0x3e8 */ + + union { + unsigned int val; + struct { + unsigned int ch2_data:10; + unsigned int ch2_enable:1; + unsigned int _11_15:5; + unsigned int in_enable:1; + unsigned int out_enable:1; + unsigned int _18_23:6; + unsigned int in_sts:1; + unsigned int out_sts:1; + unsigned int _26_30:5; + unsigned int sts:1; /* 0-plug out,1-plug in */ + } b; + } hotplug_detect; /* 0x3ec */ + + union { + unsigned int val; + struct { + unsigned int sample:8; + unsigned int _8_15:8; + unsigned int detect:9; + } b; + } hotplug_debounce; /* 0x3f0 */ + + unsigned int _3f4; + + union { + unsigned int val; + struct { + unsigned int test_enable:1; + unsigned int test_format:1; + unsigned int _2_9:8; + unsigned int infoframe_sram_enable:1; + unsigned int _11_15:5; + unsigned int clock_select:1; /* 0-clk 1x, 1-clk 2x */ + } b; + } tmds_ctrl; /* 0x3f8 */ + + unsigned int _3fc; + unsigned int rd_fifo_addr[9]; /* 0x400 - 0x420 */ +}; + +struct hdmi_base2_regs { + union { + unsigned int val; + struct { + unsigned int inv_clk:1; + unsigned int _1_3:3; + unsigned int dual_channel:1; + unsigned int _5_7:3; + unsigned int test:4; + unsigned int _12_18:7; + unsigned int internal_ldo:1; + } b; + } status; /* 0x00 */ + + union { + unsigned int val; + struct { + unsigned int drv_pdmode:1; + unsigned int _1:1; + unsigned int vbg_sel:2; + unsigned int _4_7:4; + unsigned int pd:1; + unsigned int tre_en:2; + unsigned int _11:1; + unsigned int pllck_dly:3; + unsigned int _15:1; + unsigned int pll_cpset:2; + unsigned int pll_r_f:1; + } b; + } test; /* 0x04 */ + + union { + unsigned int val; + struct { + unsigned int update:1; + unsigned int _1_7:7; + unsigned int level:1; + } b; + } level; /* 0x08 */ + + union { + unsigned int val; + struct { + unsigned int bpp_type:3; /* 0-888,1-555,2-666,3-565 */ + unsigned int _3_7:5; + unsigned int ldi_shift_left:1; /* 0-right,1-left */ + } b; + } igs; /* 0x0c */ + + union { + unsigned int val; + struct { + unsigned int out_data_12:1; /* 0-24bit,1-12bit */ + unsigned int hsync_polar_lo:1; /* 0-act hi,1-act low */ + unsigned int dvo_enable:1; + unsigned int vsync_polar_lo:1; /* 0-act hi,1-act low */ + } b; + } set; /* 0x10 */ + + union { + unsigned int val; + struct { + unsigned int colfmt_rgb:1;/* 0-RGB or YUV444,1-YUV422 */ + unsigned int colfmt_yuv422:1; + } b; + } set2; /* 0x14 */ + + union { + unsigned int val; + struct { + unsigned int pll_ready:1; + unsigned int _1_7:7; + unsigned int rsen:1; + } b; + } detect; /* 0x18 */ + + union { + unsigned int val; + struct { + unsigned int pll_tsync:1; + unsigned int tp2s_type:1; + unsigned int div_sel:2; + unsigned int pd_v2i:1; + unsigned int vco_sx:1; + unsigned int vco_mode:1; + unsigned int _7:1; + unsigned int vsref_sel:2; + unsigned int mode:1; + unsigned int pd_l2ha:1; + unsigned int pd_l2hb:1; + unsigned int l2ha_hsen:1; + unsigned int resa_en:1; + unsigned int resa_s:1; + unsigned int pll_lpfs:2; + } b; + } test2; /* 0x1c */ + + unsigned int test3; /* 0x20 */ + + union { + unsigned int val; + struct { + unsigned int _0_15:16; + unsigned int reset_pll:1; + } b; + } dftset2; /* 0x24 */ +}; + +#define REG_HDMI_BEGIN (HDMI_BASE_ADDR + 0x100) +#define REG_HDMI_END (HDMI_BASE_ADDR + 0x420) +#define REG_HDMI2_BEGIN (HDMI_BASE2_ADDR + 0x00) +#define REG_HDMI2_END (HDMI_BASE2_ADDR + 0x28) + +#ifndef HDMI_C +extern HW_REG struct hdmi_base1_regs *hdmi_regs1; +extern HW_REG struct hdmi_base2_regs *hdmi_regs2; +#endif +#endif /* WMT_HDMI_REG_H */ + diff --git a/common/wmt_display/hw/wmt-lvds-reg.h b/common/wmt_display/hw/wmt-lvds-reg.h new file mode 100755 index 0000000..0a6e616 --- /dev/null +++ b/common/wmt_display/hw/wmt-lvds-reg.h @@ -0,0 +1,129 @@ +/*++ + * linux/drivers/video/wmt/hw/wmt-lvds-reg.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef WMT_LVDS_REG_H +#define WMT_LVDS_REG_H + +#define WMT_FTBLK_LVDS + +struct lvds_base_regs { + union { + unsigned int val; + struct { + unsigned int inv_clk:1; + unsigned int _01_03:3; + unsigned int dual_channel:1; + unsigned int _05_07:3; + unsigned int test:4; + } b; + } status; /* 0x00 */ + + union { + unsigned int val; + struct { + unsigned int drv_pdmode:1; + unsigned int _01:1; + unsigned int vbg_sel:2; + unsigned int _04_07:4; + unsigned int pd:1; + unsigned int tre_en:2; + unsigned int _11:1; + unsigned int pllck_dly:3; + unsigned int _15:1; + unsigned int pll_cpset:2; + unsigned int pll_r_f:1; + } b; + } test; /* 0x04 */ + + union { + unsigned int val; + struct { + unsigned int update:1; + unsigned int _01_07:7; + unsigned int level:1; + } b; + } level; /* 0x08 */ + + union { + unsigned int val; + struct { + unsigned int bpp_type:3; /* 0-888,1-555,2-666,3-565 */ + unsigned int _03_07:5; + unsigned int ldi_shift_left:1; /* 0-shift right,1-left*/ + } b; + } igs; /* 0x0c */ + + union { + unsigned int val; + struct { + unsigned int out_data_12:1; /* 0-24bit,1-12bit */ + unsigned int hsync_polar_lo:1; /* 0-active hi,1-low */ + unsigned int dvo_enable:1; + unsigned int vsync_polar_lo:1; /* 0-active hi,1-low */ + } b; + } set; /* 0x10 */ + + union { + unsigned int val; + struct { + unsigned int colfmt:2; /* 0-YUV444,1/3-RGB,2-YUV422 */ + } b; + } set2; /* 0x14 */ + + union { + unsigned int val; + struct { + unsigned int pll_ready:1; + unsigned int _01_07:7; + unsigned int rsen:1; + } b; + } detect; /* 0x18 */ + + union { + unsigned int val; + struct { + unsigned int pll_tsync:1; + unsigned int tp2s_type:1; + unsigned int div_sel:2; + unsigned int pd_v2i:1; + unsigned int vco_sx:1; + unsigned int vco_mode:1; + unsigned int _07:1; + unsigned int vsref_sel:2; + unsigned int mode:1; + unsigned int pd_l2ha:1; + unsigned int pd_l2hb:1; + unsigned int l2ha_hsen:1; + unsigned int resa_en:1; + unsigned int resa_s:1; + unsigned int pll_lpfs:2; + } b; + } test2; /* 0x1c */ +}; + +#define REG_LVDS_BEGIN (LVDS_BASE_ADDR + 0x00) +#define REG_LVDS_END (LVDS_BASE_ADDR + 0x1C) +#ifndef LVDS_C +extern struct lvds_base_regs *lvds_regs; +#endif +#endif /* WMT_LVDS_REG_H */ diff --git a/common/wmt_display/hw/wmt-ost.h b/common/wmt_display/hw/wmt-ost.h new file mode 100755 index 0000000..024ddb6 --- /dev/null +++ b/common/wmt_display/hw/wmt-ost.h @@ -0,0 +1,37 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef WMT_OST_H +/* To assert that only one occurrence is included */ +#define WMT_OST_H + +typedef struct +{ + volatile unsigned long ostm[4]; // [Rx100-Rx10C] OS Timer Match Register0-3 + volatile unsigned long ostct; // [Rx110-113] OS Timer Counter Register + volatile unsigned long osts; // [Rx114-117] OS Timer Status Register + volatile unsigned long ostwe; // [Rx118-Rx11B] + volatile unsigned long ostie; // [Rx11C-Rx11F] + volatile unsigned long ostctrl; // [Rx120-Rx123] OS Timer Control Register + volatile unsigned long ostas; // [Rx124-Rx127] OS Timer Access Status Register +} WMT_OST_REG; + +int wmt_delayus(int us); +int wmt_read_ostc(int *val); + +#endif +/*=== END wmt-ost.h ==========================================================*/ diff --git a/common/wmt_display/hw/wmt-pwm.h b/common/wmt_display/hw/wmt-pwm.h new file mode 100755 index 0000000..e13a0a1 --- /dev/null +++ b/common/wmt_display/hw/wmt-pwm.h @@ -0,0 +1,110 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef WMT_PWM_H +/* To assert that only one occurrence is included */ +#define WMT_PWM_H + +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ + + +// Include your headers here + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* #define PWM_XXXX 1 *//*Example*/ +#define PWM_NUM_MAX 4 +#define PWM_PERIOD_VAL 1000 //modified by howayhuo . org:1000 + +#define PWM_BASE_ADDR 0xD8220000 + +// PWM Control Register +#define PWM_CTRL_REG_ADDR (PWM_BASE_ADDR+0x00) +#define PWM_ENABLE 0x01 +#define PWM_INVERT 0x02 +#define PWM_AUTOLOAD 0x04 +#define PWM_STOP_IMM 0x08 +#define PWM_LOAD_PRESCALE 0x10 +#define PWM_LOAD_PERIOD 0x20 + +// PWM Pre scalar +#define PWM_SCALAR_REG_ADDR (PWM_BASE_ADDR+0x04) +#define PWM_PRE_SCALE_MASK 0x3FF + +// PWM Period value +#define PWM_PERIOD_REG_ADDR (PWM_BASE_ADDR+0x08) +#define PWM_PERIOD_MASK 0xFFF + +// PWM Duty value +#define PWM_DUTY_REG_ADDR (PWM_BASE_ADDR+0x0C) +#define PWM_DUTY_MASK 0xFFF + +// PWM Timer Status +#define PWM_STS_REG_ADDR (PWM_BASE_ADDR+0x40) +#define PWM_CTRL_UPDATE 0x01 +#define PWM_SCALAR_UPDATE 0x02 +#define PWM_PERIOD_UPDATE 0x04 +#define PWM_DUTY_UPDATE 0x08 + +#define PWM_GPIO_CTRL_REG (0xd8110000 + 0x500) +#define PWM_GPIO_OC_REG (0xd8110000 + 0x504) +#define PWM_GPIO_OD_REG (0xd8110000 + 0x508) +#define PWM_GPIO_BIT_0 BIT4 +#define PWM_GPIO_BIT_1 BIT5 + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void pwm_xxx_t; *//*Example*/ +typedef struct { + int no; + unsigned int value; +} pwm_ctrl_t; + + +/*-------------------- EXPORTED PRIVATE VARIABLES -----------------------------*/ +#ifdef WMT_PWM_C /* allocate memory for variables only in wmt-pwm.c */ +# define EXTERN +#else +# define EXTERN extern +#endif /* ifdef WMT_PWM_C */ + +/* EXTERN int pwm_xxxx; *//*Example*/ + +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS -------------------------------*/ +#define PWM_IOC_MAGIC 'p' + +// #define PWMIOSET_THRESHOLD _IOW(PWM_IOC_MAGIC, 1, sizeof(int)) +#define PWMIOSET_ENABLE _IOW(PWM_IOC_MAGIC, 0, pwm_ctrl_t) +#define PWMIOSET_FREQ _IOW(PWM_IOC_MAGIC, 1, pwm_ctrl_t) +#define PWMIOGET_FREQ _IOWR(PWM_IOC_MAGIC, 1, pwm_ctrl_t) +#define PWMIOSET_LEVEL _IOW(PWM_IOC_MAGIC, 2, pwm_ctrl_t) +#define PWMIOGET_LEVEL _IOWR(PWM_IOC_MAGIC, 2, pwm_ctrl_t) + +#define PWM_IOC_MAXNR 3 + +/*--------------------- EXPORTED PRIVATE FUNCTIONS ---------------------------*/ +/* extern void pwm_xxxx(vdp_Void); *//*Example*/ +void pwm_set_period(int no,unsigned int period); +void pwm_set_scalar(int no,unsigned int scalar); +void pwm_set_duty(int no,unsigned int duty); +void pwm_set_enable(int no,int enable); +void pwm_set_gpio(int no,int enable); +void pwm_set_control(int no,unsigned int ctrl); + +#endif /* ifndef WMT_PWM_H */ + +/*=== END wmt-pwm.h ==========================================================*/ diff --git a/common/wmt_display/hw/wmt-scl-reg.h b/common/wmt_display/hw/wmt-scl-reg.h new file mode 100755 index 0000000..773fad9 --- /dev/null +++ b/common/wmt_display/hw/wmt-scl-reg.h @@ -0,0 +1,543 @@ +/*++ + * linux/drivers/video/wmt/hw/wmt-scl-reg.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef WMT_SCL_REG_H +#define WMT_SCL_REG_H + +/* feature */ +#define WMT_FTBLK_SCL + +/* constant */ +#define WMT_SCL_RCYC_MIN 0 /* 1T */ +#define WMT_SCL_H_DIV_MAX 8192 +#define WMT_SCL_V_DIV_MAX 8192 +#define WMT_SCL_FB_WIDTH_MAX 8192 + +#define WMT_SCL_SCALE_DST_H_MAX 1920 /* bypass no limit */ + +struct scl_base1_regs { + union { + unsigned int val; + struct { + unsigned int alu_enable:1; + } b; + } en; /* 0x0 */ + + union { + unsigned int val; + struct { + unsigned int reg_update:1; + } b; + } upd; /* 0x04 */ + + union { + unsigned int val; + struct { + unsigned int reg_level:1; + } b; + } sel; /* 0x08 */ + + unsigned int _0c_38[12]; + + union { + unsigned int val; + struct { + unsigned int hxwidth:13; + } b; + } hxwidth; /* 0x3c */ + + union { + unsigned int val; + struct { + unsigned int mif_en:1; + unsigned int _01_03:3; + unsigned int rgb_mode:2; /* 0-YUV,1-RGB565,3-RGB32 */ + unsigned int _06_07:2; + unsigned int _420c_fmt:1; /* 0-frame,1-field */ + unsigned int vfmt:3; /* 0-YUV422,1-YUV420, + 2-YUV444,4-RGB32 */ + unsigned int h264_fmt:1; /* 0-MPEG,1-H264 */ + unsigned int _13_15:3; + unsigned int iofmt:1; /* 0-frame,1-field */ + unsigned int _17_23:7; + unsigned int color_en:1; /* 0-disable,1-enable */ + unsigned int color_wide:1; /* 0-Normal,1-Wider */ + unsigned int color_inv:1; /* 0-Normal,1-Opposite color*/ + } b; + } r2_ctl; /* 0x40 */ + + unsigned int r2_ysa; /* 0x44 */ + unsigned int r2_csa; /* 0x48 */ + + union { + unsigned int val; + struct { + unsigned int fbw:13; /* frame buffer width pixel */ + unsigned int _13_15:3; + unsigned int lnsize:13; /* line width pixel */ + } b; + } r2_h_size; /* 0x4c */ + + union { + unsigned int val; + struct { + unsigned int hcrop:13; + unsigned int _13_15:3; + unsigned int vcrop:13; + } b; + } r2_crop; /* 0x50 */ + + union { + unsigned int val; + struct { + unsigned int src:2; /* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */ + unsigned int _02_07:6; + unsigned int dst:2; /* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */ + unsigned int _09_15:6; + unsigned int swap:1; /* 0-(alpha,1-a),1:(1-a,alpha) */ + } b; + } alpha_md; /* 0x54 */ + + union { + unsigned int val; + struct { + unsigned int src_fixed:8; + unsigned int dst_fixed:8; + } b; + } alpha_fxd; /* 0x58 */ + + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int _01_07:7; + unsigned int from:1; /* 0-RMIF1,1-RMIF2 */ + unsigned int _09_15:7; + unsigned int comp:2; /* 0-888,1-777,2-666,3-555 */ + unsigned int _17_23:7; + unsigned int mode:3; /* (Non-Hit,Hit):0/1-(alpha,alpha), + 2-(alpha,pix1),3-(pix1,alpha),4-(alpha,pix2), + 5-(pix2,alpha),6-(pix1,pix2),7-(pix2,pix1) */ + } b; + } alpha_colorkey; /* 0x5c */ + + union { + unsigned int val; + struct { + unsigned int r:8; + unsigned int g:8; + unsigned int b:8; + } b; + } alpha_colorkey_rgb; /* 0x60 */ + + unsigned int _64_6c[3]; + + union { + unsigned int val; + struct { + unsigned int vxwidth:13; + unsigned int _13_15:3; + unsigned int dst_vxwidth:13; + } b; + } vxwidth; /* 0x70 */ + + union { + unsigned int val; + struct { + unsigned int h:1; + unsigned int _01_15:15; + unsigned int v:1; + } b; + } sclup_en; /* 0x74 */ + + union { + unsigned int val; + struct { + unsigned int thr:13; + unsigned int _13_15:3; + unsigned int substep:13; + } b; + } vscale1; /* 0x78 */ + + union { + unsigned int val; + struct { + unsigned int substepcnt:13; + unsigned int _13_15:3; + unsigned int step:13; + } b; + } vscale2; /* 0x7c */ + + union { + unsigned int val; + struct { + unsigned int stepcnt:17; + } b; + } vscale3; /* 0x80 */ + + union { + unsigned int val; + struct { + unsigned int thr:13; + unsigned int _13_15:3; + unsigned int substep:13; + } b; + } hscale1; /* 0x84 */ + + union { + unsigned int val; + struct { + unsigned int substepcnt:13; + unsigned int _13_15:3; + unsigned int step:13; + } b; + } hscale2; /* 0x88 */ + + union { + unsigned int val; + struct { + unsigned int stepcnt:17; + } b; + } hscale3; /* 0x8c */ + + union { + unsigned int val; + struct { + unsigned int y_req_num:8; + unsigned int c_req_num:8; + } b; + } r_req_num; /* 0x90 */ + + unsigned int scldw; /* 0x94 */ /* (VPU path, scale dn) + 0 - bilinear mode, quality better */ + unsigned int sw_426; /* 0x98 */ /* 1-follow 426, 0-437 */ + unsigned int vbypass; /* 0x9c */ + + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int _1_3:3; + unsigned int err_off:1; /*disable TG_EN in tg timeout*/ + unsigned int _5_7:3; + unsigned int watchdog_enable:1; + unsigned int _9_15:7; + unsigned int rdcyc:8; + unsigned int oneshot:1; /* sacling complete will set + SCL tg enable to 0 */ + } b; + } tg_ctl; /* 0xa0 */ + + union { + unsigned int val; + struct { + unsigned int h_allpixel:13; + unsigned int _13_15:3; + unsigned int v_allline:13; + } b; + } tg_total; /* 0xa4 */ + + union { + unsigned int val; + struct { + unsigned int v_actbg:8; + unsigned int _8_15:8; + unsigned int v_actend:13; + } b; + } tg_v_active; /* 0xa8 */ + + union { + unsigned int val; + struct { + unsigned int h_actbg:10; + unsigned int _10_15:6; + unsigned int h_actend:13; + } b; + } tg_h_active; /* 0xac */ + + union { + unsigned int val; + struct { + unsigned int vbie:7; + unsigned int _7:1; + unsigned int pvbi:5; + } b; + } tg_vbi; /* 0xb0 */ + + unsigned int tg_watchdog; /* 0xb4 */ + + union { + unsigned int val; + struct { + unsigned int tgerr:1; + } b; + } tg_sts; /* 0xb8 */ + + union { + unsigned int val; + struct { + unsigned int enable:1; + } b; + } tg_govw; /* 0xbc */ + + union { + unsigned int val; + struct { + unsigned int mif_enable:1; /*0:Disable, 1:Enable */ + unsigned int _1_3:3; + unsigned int rgb_mode:2; /*0:YC,1:RGB565,3:RGB32 */ + unsigned int _6_7:2; + unsigned int src_disp_fmt:1; /*420C 0:Frame, 1:Field */ + unsigned int yuv:2; /*0:422,1:420,2:444*/ + unsigned int rgb:1; /*0:YCbCr, 1:RGB32 */ + unsigned int h264:1; /*0:MPEG, 1:H264 */ + unsigned int _13_15:3; + unsigned int field:1; /*0:Frame, 1:Field */ + unsigned int _17_23:7; + unsigned int colorbar_enable:1; + unsigned int colorbar_mode:1; + unsigned int colorbar_inv:1; + } b; + } r_ctl; /* 0xc0 */ + + unsigned int r_ysa; /* 0xc4 */ + unsigned int r_csa; /* 0xc8 */ + + union { + unsigned int val; + struct { + unsigned int fb_w:13; + unsigned int _13_15:3; + unsigned int pix_w:13; + } b; + } r_h_size; /* 0xcc */ + + union { + unsigned int val; + struct { + unsigned int hcrop:13; + unsigned int _13_15:3; + unsigned int vcrop:13; + } b; + } r_crop; /* 0xd0 */ + + union { + unsigned int val; + struct { + unsigned int thr:4; + unsigned int _4_7:4; + unsigned int r1_mif_err:1; + unsigned int r2_mif_err:1; + } b; + } r_fifo_ctl; /* 0xd4 */ + + unsigned int _d8_dc[2]; + + union { + unsigned int val; + struct { + unsigned int mif_enable:1; + unsigned int _1_7:7; + unsigned int yuv:1; /* 0-444,1-422 */ + unsigned int rgb:1; /* 0-YC,1-RGB32 */ + } b; + } w_ctl; /* 0xe0 */ + + unsigned int w_ysa; /* 0xe4 */ + unsigned int w_csa; /* 0xe8 */ + + union { + unsigned int val; + struct { + unsigned int fb_w:13; + unsigned int _13_15:3; + unsigned int pxl_w:13; + } b; + } w_y_time; /* 0xec */ + + union { + unsigned int val; + struct { + unsigned int fb_w:13; + unsigned int _13_15:3; + unsigned int pxl_w:12; + } b; + } w_c_time; /* 0xf0 */ + + union { + unsigned int val; + struct { + unsigned int mif_c_err:1; + unsigned int _1_7:7; + unsigned int mif_y_err:1; + unsigned int _9_15:7; + unsigned int mif_rgb_err:1; + } b; + } w_ff_ctl; /* 0xf4 */ + + union { + unsigned int val; + struct { + unsigned int mif_c_err:1; + unsigned int mif_y_err:1; + unsigned int mif_rgb_err:1; + unsigned int _3_7:5; + unsigned int r2_mif_enable:1; + unsigned int r1_mif_enable:1; + unsigned int _10_15:6; + unsigned int tg_err:1; + } b; + } w_int_en; /* 0xf8 */ + + union { + unsigned int val; + struct { + unsigned int h:1; + unsigned int _1_7:7; + unsigned int v:1; + } b; + } true_bilinear; /* 0xfc */ +}; + +struct scl_base2_regs { + union { + unsigned int val; + struct { + unsigned int mode:1; /* 0-RGB2YC,1-YC2RGB */ + unsigned int _01_07:7; + unsigned int clamp_enable:1; /* clamp to 16-235 */ + unsigned int _09_15:7; + unsigned int enable:1; + } b; + } csc_ctl; /* 0x0 */ + + unsigned int csc1; /* 0x4 */ + unsigned int csc2; /* 0x8 */ + unsigned int csc3; /* 0xc */ + unsigned int csc4; /* 0x10 */ + unsigned int csc5; /* 0x14 */ + unsigned int csc6; /* 0x18 */ + + union { + unsigned int val; + struct { + unsigned int enable:1; + unsigned int _01_07:7; + unsigned int data:8; + } b; + } argb_alpha; /* 0x1c */ + + union { + unsigned int val; + struct { + unsigned int mode:2; /* 0-888,1-555,2-666,3-565 */ + } b; + } igs; /* 0x20 */ + + union { + unsigned int val; + struct { + unsigned int mode:1; /* 0-CCIR/ITU-601 */ + unsigned int _01_07:7; + unsigned int clamp:1; /* 0-direct,1-16-235 */ + unsigned int _09_15:7; + unsigned int enable:1; + } b; + } r2_csc; /* 0x24 */ + + unsigned int r2_csc1; /* 0x28 */ + unsigned int r2_csc2; /* 0x2c */ + unsigned int r2_csc3; /* 0x30 */ + unsigned int r2_csc4; /* 0x34 */ + unsigned int r2_csc5; /* 0x38 */ + unsigned int r2_csc6; /* 0x3c */ + unsigned int _40_9c[24]; + + union { + unsigned int val; + struct { + unsigned int h:1; + unsigned int _01_07:7; + unsigned int v:1; + } b; + } recursive_mode; /* 0xa0 */ + + unsigned int _a4_bc[7]; + + union { + unsigned int val; + struct { + unsigned int deblock:1; + unsigned int field_deflicker:1; + unsigned int frame_deflicker:1; + } b; + } field_mode; /* 0xc0 */ + + union { + unsigned int val; + struct { + unsigned int layer1_boundary:8; + unsigned int layer2_boundary:8; + } b; + } dblk_threshold; /* 0xc4 */ + + union { + unsigned int val; + struct { + unsigned int condition:1; /* 0-up or down,1-up & down */ + unsigned int _01_07:7; + unsigned int y_thd:8; + unsigned int c_thd:8; + } b; + } field_flicker; /* 0xc8 */ + union { + unsigned int val; + struct { + unsigned int rgb:1; /* 0-Y,1-RGB */ + unsigned int _01_07:7; + unsigned int sampler:5; /* 2^x */ + unsigned int _13_15:3; + unsigned int scene_chg_thd:8; + } b; + } frame_flicker; /* 0xcc */ + + union { + unsigned int val; + struct { + unsigned int rdcyc_1t:1; + } b; + } readcyc_1t; /* 0xd0 */ + + unsigned int _d4_e0[4]; +}; + +#define REG_SCL_BASE1_BEGIN (SCL_BASE_ADDR + 0x00) +#define REG_SCL_BASE1_END (SCL_BASE_ADDR + 0xFC) +#define REG_SCL_BASE2_BEGIN (SCL_BASE2_ADDR + 0x00) +#define REG_SCL_BASE2_END (SCL_BASE2_ADDR + 0xE0) + +#ifndef SCL_C +extern HW_REG struct scl_base1_regs *scl_regs1; +extern HW_REG struct scl_base2_regs *scl_regs2; +#endif +#endif /* WMT_SCL_REG_H */ diff --git a/common/wmt_display/hw/wmt-vpp-hw.h b/common/wmt_display/hw/wmt-vpp-hw.h new file mode 100755 index 0000000..599ebe0 --- /dev/null +++ b/common/wmt_display/hw/wmt-vpp-hw.h @@ -0,0 +1,137 @@ +/*++ + * linux/drivers/video/wmt/hw/wmt-vpp-hw.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef WMT_VPP_HW_H +#define WMT_VPP_HW_H + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* +* Product ID / Project ID +* 84xx series: 8420/3300, 8430/3357, 8435/3437 +* 85xx series: 8500/3400, 8510/3426, 8520/3429 +*/ +/* 84xx series, (1-100) with VDU & DSP */ +#define VIA_PID_8420 10 /* 3300 */ +#define VIA_PID_8430 12 /* 3357 */ +#define WMT_PID_8435 14 /* 3437 */ +#define WMT_PID_8440 16 /* 3451 */ +#define WMT_PID_8425 18 /* 3429 */ +#define WMT_PID_8710 20 /* 3445 */ +#define WMT_PID_8950 22 /* 3481 */ +#define WMT_PID_8980 24 /* 3498 */ + +/* 85xx series, (101-200) */ +#define VIA_PID_8500 110 /* 3400 */ +#define WMT_PID_8505 111 +#define WMT_PID_8510 112 /* 3426* */ + +#define WMT_PID_8950_A 1 + +/* current pid */ +#define WMT_CUR_PID WMT_PID_8980 +#define WMT_SUB_PID 0 + +/* #define WMT_SUB_PID WMT_PID_8505 */ +#ifndef WMT_SUB_PID + #define WMT_SUB_PID 0 +#endif + +/* VPP interrupt map to irq */ +#define VPP_IRQ_SCL_FINISH IRQ_VPP_IRQ0 +#define VPP_IRQ_SCL IRQ_VPP_IRQ1 +#define VPP_IRQ_SCL444_TG IRQ_VPP_IRQ2 +#define VPP_IRQ_VPPM IRQ_VPP_IRQ3 +#define VPP_IRQ_GOVW_TG IRQ_VPP_IRQ4 +#define VPP_IRQ_GOVW IRQ_VPP_IRQ5 +#define VPP_IRQ_GOVM IRQ_VPP_IRQ6 +#define VPP_IRQ_GE IRQ_VPP_IRQ7 +#define VPP_IRQ_GOVRH_TG IRQ_VPP_IRQ8 /* PVBI or VBIS or VBIE */ +#define VPP_IRQ_DVO IRQ_VPP_IRQ9 +#define VPP_IRQ_VID IRQ_VPP_IRQ10 +#define VPP_IRQ_GOVR IRQ_VPP_IRQ11 /* underrun & mif */ +#define VPP_IRQ_GOVRSD_TG IRQ_VPP_IRQ12 +#define VPP_IRQ_VPU IRQ_VPP_IRQ13 +#define VPP_IRQ_VPU_TG IRQ_VPP_IRQ14 +#define VPP_IRQ_HDMI_CP IRQ_VPP_IRQ15 +#define VPP_IRQ_HDMI_HPDH IRQ_VPP_IRQ16 +#define VPP_IRQ_HDMI_HPDL IRQ_VPP_IRQ17 +#define VPP_IRQ_GOVR_0 IRQ_VPP_IRQ18 +#define VPP_IRQ_GOVR_2 IRQ_VPP_IRQ19 +#define VPP_IRQ_CEC IRQ_VPP_IRQ20 +#define VPP_IRQ_GOVR2_0 IRQ_VPP_IRQ21 +#define VPP_IRQ_GOVR2 IRQ_VPP_IRQ22 +#define VPP_IRQ_GOVR2_2 IRQ_VPP_IRQ23 +#define VPP_IRQ_DVO2 IRQ_VPP_IRQ24 +#define VPP_IRQ_GOVR2_TG IRQ_VPP_IRQ25 + +/* DVI I2C */ +#define VPP_DVI_I2C_DEFAULT 1 /* default i2c bus */ +#define VPP_DVI_I2C_SW_BIT 0x10 /* hw or sw i2c */ +#define VPP_DVI_I2C_ID_MASK 0x1F +#define VPP_DVI_I2C_ID g_vpp.dvi_i2c_no +#define VPP_DVI_EDID_ID (VPP_DVI_I2C_SW_BIT + 0x1) /* DVO EDID use + sw i2c bus 1 */ + +/* vout */ +#define VPP_VOUT_INFO_NUM 5 /* linux fb or govr number */ + +#define VPP_VOUT_NUM 2 +#define VPP_VOUT_ALL 0xFFFFFFFF +#define VPP_VOUT_NUM_HDMI 0 +#define VPP_VOUT_NUM_LVDS 1 +#define VPP_VOUT_NUM_DVI 1 + +#define WMT_FTBLK_VOUT_DVI +#define WMT_FTBLK_VOUT_HDMI +#define WMT_FTBLK_VOUT_LVDS + +/* hw parameter */ +#define VPP_DVI_INT_DEFAULT 0 /* default interrupt gpio */ +#define VPP_VOINT_NO g_vpp.dvi_int_no +#define VPP_UBOOT_COLFMT VDO_COL_FMT_RGB_565 +#define VPP_FB_ADDR_ALIGN 64 +#define VPP_FB_WIDTH_ALIGN 64 /* hw should 4 byte align,android + framework 8 byte align modify by aksenxu VPU need 64bytes alignment + you need modify FramebufferNativeWindow::FramebufferNativeWindow + in android framework together */ +#define VPP_GOVR_DVO_DELAY_24 0x4036 +#define VPP_GOVR_DVO_DELAY_12 0x120 + +/*-------------------- DEPENDENCY -------------------------------------*/ +#ifdef __KERNEL__ +#ifndef CONFIG_WMT_HDMI +#undef WMT_FTBLK_VOUT_HDMI +#endif +#endif + +#include "wmt-vpp-reg.h" +#include "wmt-govrh-reg.h" +#include "wmt-lvds-reg.h" +#ifdef WMT_FTBLK_VOUT_HDMI +#include "wmt-hdmi-reg.h" +#endif +#include "wmt-scl-reg.h" +#ifndef CONFIG_UBOOT +#include "wmt-cec-reg.h" +#endif +#endif /* WMT_VPP_HW_H */ diff --git a/common/wmt_display/hw/wmt-vpp-reg.h b/common/wmt_display/hw/wmt-vpp-reg.h new file mode 100755 index 0000000..b96e64d --- /dev/null +++ b/common/wmt_display/hw/wmt-vpp-reg.h @@ -0,0 +1,132 @@ +/*++ + * linux/drivers/video/wmt/hw/wmt-vpp-reg.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef WMT_VPP_REG_H +#define WMT_VPP_REG_H + +#define VPP_DAC_SEL_TV 1 +#define VPP_DAC_SEL_VGA 0 + +struct vppm_base_regs { + unsigned int _00; /* 0x00 */ + + union { + unsigned int val; + struct { + unsigned int _0_7:8; + unsigned int govrh_pvbi:1; + unsigned int govrh_vbis:1; + unsigned int govrh_vbie:1; + unsigned int _11:1; + unsigned int govrh2_pvbi:1; + unsigned int govrh2_vbis:1; + unsigned int govrh2_vbie:1; + unsigned int _15:1; + unsigned int scl_pvbi:1; + unsigned int scl_vbis:1; + unsigned int scl_vbie:1; + unsigned int _19:1; + unsigned int ge_tg:1; + } b; + } int_sts; /* 0x4 */ + + union { + unsigned int val; + struct { + unsigned int _0_7:8; + unsigned int govrh_pvbi:1; + unsigned int govrh_vbis:1; + unsigned int govrh_vbie:1; + unsigned int _11:1; + unsigned int govrh2_pvbi:1; + unsigned int govrh2_vbis:1; + unsigned int govrh2_vbie:1; + unsigned int _15:1; + unsigned int scl_pvbi:1; + unsigned int scl_vbis:1; + unsigned int scl_vbie:1; + unsigned int _19:1; + unsigned int ge_tg:1; + } b; + } int_en; /* 0x8 */ + + unsigned int watch_sel; /* 0x0C */ + + union { + unsigned int val; + struct { + unsigned int scl:1; + unsigned int _1_7:7; + unsigned int vid:1; + unsigned int _9_15:7; + unsigned int ge:1; + } b; + } sw_reset1; /* 0x10 */ + + union { + unsigned int val; + struct { + unsigned int govrh:1; + unsigned int _1_3:3; + unsigned int lvds:1; + unsigned int _5_7:3; + unsigned int dvo:1; + unsigned int dvo2:1; + unsigned int _10_11:2; + unsigned int cec:1; + } b; + } sw_reset2; /* 0x14 */ + + unsigned int dac_sel; /* 0x18 */ + + union { + unsigned int val; + struct { + unsigned int hdmi:1; + unsigned int _1_7:7; + unsigned int ddc:1; + unsigned int _9_15:7; + unsigned int hdmi2:1; + } b; + } sw_reset3; /* 0x1C */ + + union { + unsigned int val; + struct { + unsigned int disable:1; + unsigned int _1_7:7; + unsigned int csi_act_lane_sel:1; /*0-lane 0/1,1-2/3*/ + } b; + } sscg; /* 0x20 */ +}; + +#define REG_VPP_BEGIN (VPP_BASE_ADDR + 0x00) +#define REG_VPP_END (VPP_BASE_ADDR + 0x28) + +#ifndef VPPM_C +extern HW_REG struct vppm_base_regs *vppm_regs; +#endif + + +#endif /* WMT_VPP_REG_H */ + diff --git a/common/wmt_display/hw/wmt_gpio.h b/common/wmt_display/hw/wmt_gpio.h new file mode 100755 index 0000000..0f5cf87 --- /dev/null +++ b/common/wmt_display/hw/wmt_gpio.h @@ -0,0 +1,791 @@ +/*++ +linux/arch/arm/mach-wmt/include/mach/wmt_gpio.h + +Copyright (c) 2014 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software Foundation, +either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/* Be sure that virtual mapping is defined right */ + +#ifndef __WMT_GPIO_H +/* To assert that only one occurrence is included */ +#define __WMT_GPIO_H + +/*-------------------- MODULE DEPENDENCY ------------------------------------*/ +#ifndef APPLICATION +#else +#endif + + +/*-------------------- EXPORTED PRIVATE CONSTANTS ---------------------------*/ + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ + +/*-------------------- EXPORTED PRIVATE VARIABLES -----------------------------*/ +#ifdef XXX_C /* allocate memory for variables only in xxx.c */ +# define EXTERN +#else +# define EXTERN extern +#endif /* ifdef XXX_C */ + + +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS -------------------------------*/ +#define __GPIO_BASE GPIO_BASE_ADDR + +#define GIRQ_LOW 0x00 /* Input zero generate GPIO_IRQ signal */ +#define GIRQ_HIGH 0x01 /* Input one generate GPIO_IRQ signal */ +#define GIRQ_FALLING 0x02 /* Falling edge generate GPIO_IRQ signal */ +#define GIRQ_RISING 0x03 /* Rising edge generate GPIO_IRQ signal */ +#define GIRQ_BOTHEDGE 0x04 +#define GIRQ_TYPEMASK 0x07 +#define GIRQ_TYPE(idx, type) ((type & GIRQ_TYPEMASK) << (idx * 8)) /* idx must be 0-3 */ +#define GIRQ_EN_STS(idx) ( 1 << ((idx+1)*8-1) ) /* idx must be 0-3 */ + +#define GPIO_ID_GP0_BYTE_ADDR (__GPIO_BASE + 0x00 )/* [0x0] */ +#define GPIO_ID_GP1_BYTE_ADDR (__GPIO_BASE + 0x01 )/* [0x1] */ +#define GPIO_ID_GP2_BYTE_ADDR (__GPIO_BASE + 0x02 )/* [0x2] */ +#define GPIO_ID_GP4_VDOUT_7_0_BYTE_ADDR (__GPIO_BASE + 0x04 )/* [0x4] */ +#define GPIO_ID_GP5_VDOUT_15_8_BYTE_ADDR (__GPIO_BASE + 0x05 )/* [0x5] */ +#define GPIO_ID_GP6_VDOUT_23_16_BYTE_ADDR (__GPIO_BASE + 0x06 )/* [0x6] */ +#define GPIO_ID_GP7_VD_BYTE_ADDR (__GPIO_BASE + 0x07 )/* [0x7] */ +#define GPIO_ID_GP8_VDIN_BYTE_ADDR (__GPIO_BASE + 0x08 )/* [0x8] */ +#define GPIO_ID_GP9_VSYNC_BYTE_ADDR (__GPIO_BASE + 0x09 )/* [0x9] */ +#define GPIO_ID_GP10_I2S_BYTE_ADDR (__GPIO_BASE + 0x0A )/* [0xA] */ +#define GPIO_ID_GP11_I2S_BYTE_ADDR (__GPIO_BASE + 0x0B )/* [0xB] */ +#define GPIO_ID_GP12_SPI_BYTE_ADDR (__GPIO_BASE + 0x0C )/* [0xC] */ +#define GPIO_ID_GP13_SD0_BYTE_ADDR (__GPIO_BASE + 0x0D )/* [0xD] */ +#define GPIO_ID_GP14_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0x0E )/* [0xE] */ +#define GPIO_ID_GP15_NAND_BYTE_ADDR (__GPIO_BASE + 0x0F )/* [0xF] */ +#define GPIO_ID_GP16_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0x10 )/* [0x10] */ +#define GPIO_ID_GP17_I2C_BYTE_ADDR (__GPIO_BASE + 0x11 )/* [0x11] */ +#define GPIO_ID_GP18_UART_BYTE_ADDR (__GPIO_BASE + 0x12 )/* [0x12] */ +#define GPIO_ID_GP19_SD2_BYTE_ADDR (__GPIO_BASE + 0x13 )/* [0x13] */ +#define GPIO_ID_GP20_PWM0_BYTE_ADDR (__GPIO_BASE + 0x14 )/* [0x14] */ +#define GPIO_ID_GP21_HDMI_BYTE_ADDR (__GPIO_BASE + 0x15 )/* [0x15] */ +#define GPIO_ID_GP23_I2C3_BYTE_ADDR (__GPIO_BASE + 0x17 )/* [0x17] */ +#define GPIO_ID_GP24_SF_BYTE_ADDR (__GPIO_BASE + 0x18 )/* [0x18] */ +#define GPIO_ID_GP26_PCM_BYTE_ADDR (__GPIO_BASE + 0x1A )/* [0x1A] */ +#define GPIO_ID_GP60_USB_BYTE_ADDR (__GPIO_BASE + 0x3C )/* [0x3C] */ +#define GPIO_ID_GP62_WAKEUP_SUS_BYTE_ADDR (__GPIO_BASE + 0x3E )/* [0x3E] */ +#define GPIO_ID_GP63_SD02CD_BYTE_ADDR (__GPIO_BASE + 0x3F )/* [0x3F] */ +#define GPIO_CTRL_GP0_BYTE_ADDR (__GPIO_BASE + 0x40 )/* [0x40] */ +#define GPIO_CTRL_GP1_BYTE_ADDR (__GPIO_BASE + 0x41 )/* [0x41] */ +#define GPIO_CTRL_GP2_BYTE_ADDR (__GPIO_BASE + 0x42 )/* [0x42] */ +#define GPIO_CTRL_GP4_VDOUT_7_0_BYTE_ADDR (__GPIO_BASE + 0x44 )/* [0x44] */ +#define GPIO_CTRL_GP5_VDOUT_15_8_BYTE_ADDR (__GPIO_BASE + 0x45 )/* [0x45] */ +#define GPIO_CTRL_GP6_VDOUT_23_16_BYTE_ADDR (__GPIO_BASE + 0x46 )/* [0x46] */ +#define GPIO_CTRL_GP7_VD_BYTE_ADDR (__GPIO_BASE + 0x47 )/* [0x47] */ +#define GPIO_CTRL_GP8_VDIN_BYTE_ADDR (__GPIO_BASE + 0x48 )/* [0x48] */ +#define GPIO_CTRL_GP9_VSYNC_BYTE_ADDR (__GPIO_BASE + 0x49 )/* [0x49] */ +#define GPIO_CTRL_GP10_I2S_BYTE_ADDR (__GPIO_BASE + 0x4A )/* [0x4A] */ +#define GPIO_CTRL_GP11_I2S_BYTE_ADDR (__GPIO_BASE + 0x4B )/* [0x4B] */ +#define GPIO_CTRL_GP12_SPI_BYTE_ADDR (__GPIO_BASE + 0x4C )/* [0x4C] */ +#define GPIO_CTRL_GP13_SD0_BYTE_ADDR (__GPIO_BASE + 0x4D )/* [0x4D] */ +#define GPIO_CTRL_GP14_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0x4E )/* [0x4E] */ +#define GPIO_CTRL_GP15_NAND_BYTE_ADDR (__GPIO_BASE + 0x4F )/* [0x4F] */ +#define GPIO_CTRL_GP16_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0x50 )/* [0x50] */ +#define GPIO_CTRL_GP17_I2C_BYTE_ADDR (__GPIO_BASE + 0x51 )/* [0x51] */ +#define GPIO_CTRL_GP18_UART_BYTE_ADDR (__GPIO_BASE + 0x52 )/* [0x52] */ +#define GPIO_CTRL_GP19_SD2_BYTE_ADDR (__GPIO_BASE + 0x53 )/* [0x53] */ +#define GPIO_CTRL_GP20_PWM0_BYTE_ADDR (__GPIO_BASE + 0x54 )/* [0x54] */ +#define GPIO_CTRL_GP21_HDMI_BYTE_ADDR (__GPIO_BASE + 0x55 )/* [0x55] */ +#define GPIO_CTRL_GP23_I2C3_BYTE_ADDR (__GPIO_BASE + 0x57 )/* [0x57] */ +#define GPIO_CTRL_GP24_SF_BYTE_ADDR (__GPIO_BASE + 0x58 )/* [0x58] */ +#define GPIO_CTRL_GP26_PCM_BYTE_ADDR (__GPIO_BASE + 0x5A )/* [0x5A] */ +#define GPIO_CTRL_GP60_USB_BYTE_ADDR (__GPIO_BASE + 0x7C )/* [0x7C] */ +#define GPIO_CTRL_GP62_WAKEUP_SUS_BYTE_ADDR (__GPIO_BASE + 0x7E )/* [0x7E] */ +#define GPIO_CTRL_GP63_SD02CD_BYTE_ADDR (__GPIO_BASE + 0x7F )/* [0x7F] */ +#define GPIO_OC_GP0_BYTE_ADDR (__GPIO_BASE + 0x80 )/* [0x80] */ +#define GPIO_OC_GP1_BYTE_ADDR (__GPIO_BASE + 0x81 )/* [0x81] */ +#define GPIO_OC_GP2_BYTE_ADDR (__GPIO_BASE + 0x82 )/* [0x82] */ +#define GPIO_OC_GP4_VDOUT_7_0_BYTE_ADDR (__GPIO_BASE + 0x84 )/* [0x84] */ +#define GPIO_OC_GP5_VDOUT_15_8_BYTE_ADDR (__GPIO_BASE + 0x85 )/* [0x85] */ +#define GPIO_OC_GP6_VDOUT_23_16_BYTE_ADDR (__GPIO_BASE + 0x86 )/* [0x86] */ +#define GPIO_OC_GP7_VD_BYTE_ADDR (__GPIO_BASE + 0x87 )/* [0x87] */ +#define GPIO_OC_GP8_VDIN_BYTE_ADDR (__GPIO_BASE + 0x88 )/* [0x88] */ +#define GPIO_OC_GP9_VSYNC_BYTE_ADDR (__GPIO_BASE + 0x89 )/* [0x89] */ +#define GPIO_OC_GP10_I2S_BYTE_ADDR (__GPIO_BASE + 0x8A )/* [0x8A] */ +#define GPIO_OC_GP11_I2S_BYTE_ADDR (__GPIO_BASE + 0x8B )/* [0x8B] */ +#define GPIO_OC_GP12_SPI_BYTE_ADDR (__GPIO_BASE + 0x8C )/* [0x8C] */ +#define GPIO_OC_GP13_SD0_BYTE_ADDR (__GPIO_BASE + 0x8D )/* [0x8D] */ +#define GPIO_OC_GP14_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0x8E )/* [0x8E] */ +#define GPIO_OC_GP15_NAND_BYTE_ADDR (__GPIO_BASE + 0x8F )/* [0x8F] */ +#define GPIO_OC_GP16_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0x90 )/* [0x90] */ +#define GPIO_OC_GP17_I2C_BYTE_ADDR (__GPIO_BASE + 0x91 )/* [0x91] */ +#define GPIO_OC_GP18_UART_BYTE_ADDR (__GPIO_BASE + 0x92 )/* [0x92] */ +#define GPIO_OC_GP19_SD2_BYTE_ADDR (__GPIO_BASE + 0x93 )/* [0x93] */ +#define GPIO_OC_GP20_PWM0_BYTE_ADDR (__GPIO_BASE + 0x94 )/* [0x94] */ +#define GPIO_OC_GP21_HDMI_BYTE_ADDR (__GPIO_BASE + 0x95 )/* [0x95] */ +#define GPIO_OC_GP22_I2C3_BYTE_ADDR (__GPIO_BASE + 0x96 )/* [0x96] */ +#define GPIO_OC_GP24_SF_BYTE_ADDR (__GPIO_BASE + 0x98 )/* [0x98] */ +#define GPIO_OC_GP26_PCM_BYTE_ADDR (__GPIO_BASE + 0x9A )/* [0x9A] */ +#define GPIO_OC_GP60_USB_BYTE_ADDR (__GPIO_BASE + 0xBC )/* [0xBC] */ +#define GPIO_OC_GP62_WAKEUP_SUS_BYTE_ADDR (__GPIO_BASE + 0xBE )/* [0xBE] */ +#define GPIO_OC_GP63_SD02CD_BYTE_ADDR (__GPIO_BASE + 0xBF )/* [0xBF] */ +#define GPIO_OD_GP0_BYTE_ADDR (__GPIO_BASE + 0xC0 )/* [0xC0] */ +#define GPIO_OD_GP1_BYTE_ADDR (__GPIO_BASE + 0xC1 )/* [0xC1] */ +#define GPIO_OD_GP2_BYTE_ADDR (__GPIO_BASE + 0xC2 )/* [0xC2] */ +#define GPIO_OD_GP4_VDOUT_7_0_BYTE_ADDR (__GPIO_BASE + 0xC4 )/* [0xC4] */ +#define GPIO_OD_GP5_VDOUT_15_8_BYTE_ADDR (__GPIO_BASE + 0xC5 )/* [0xC5] */ +#define GPIO_OD_GP6_VDOUT_23_16_BYTE_ADDR (__GPIO_BASE + 0xC6 )/* [0xC6] */ +#define GPIO_OD_GP7_VD_BYTE_ADDR (__GPIO_BASE + 0xC7 )/* [0xC7] */ +#define GPIO_OD_GP8_VDIN_BYTE_ADDR (__GPIO_BASE + 0xC8 )/* [0xC8] */ +#define GPIO_OD_GP9_VSYNC_BYTE_ADDR (__GPIO_BASE + 0xC9 )/* [0xC9] */ +#define GPIO_OD_GP10_I2S_BYTE_ADDR (__GPIO_BASE + 0xCA )/* [0xCA] */ +#define GPIO_OD_GP11_I2S_BYTE_ADDR (__GPIO_BASE + 0xCB )/* [0xCB] */ +#define GPIO_OD_GP12_SPI_BYTE_ADDR (__GPIO_BASE + 0xCC )/* [0xCC] */ +#define GPIO_OD_GP13_SD0_BYTE_ADDR (__GPIO_BASE + 0xCD )/* [0xCD] */ +#define GPIO_OD_GP14_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0xCE )/* [0xCE] */ +#define GPIO_OD_GP15_NAND_BYTE_ADDR (__GPIO_BASE + 0xCF )/* [0xCF] */ +#define GPIO_OD_GP16_NAND_SD1_BYTE_ADDR (__GPIO_BASE + 0xD0 )/* [0xD0] */ +#define GPIO_OD_GP17_I2C_BYTE_ADDR (__GPIO_BASE + 0xD1 )/* [0xD1] */ +#define GPIO_OD_GP18_UART_BYTE_ADDR (__GPIO_BASE + 0xD2 )/* [0xD2] */ +#define GPIO_OD_GP19_SD2_BYTE_ADDR (__GPIO_BASE + 0xD3 )/* [0xD3] */ +#define GPIO_OD_GP20_PWM0_BYTE_ADDR (__GPIO_BASE + 0xD4 )/* [0xD4] */ +#define GPIO_OD_GP21_HDMI_BYTE_ADDR (__GPIO_BASE + 0xD5 )/* [0xD5] */ +#define GPIO_OD_GP23_I2C3_BYTE_ADDR (__GPIO_BASE + 0xD7 )/* [0xD7] */ +#define GPIO_OD_GP24_SF_BYTE_ADDR (__GPIO_BASE + 0xD8 )/* [0xD8] */ +#define GPIO_OD_GP26_PCM_BYTE_ADDR (__GPIO_BASE + 0xDA )/* [0xDA] */ +#define GPIO_OD_GP60_USB_BYTE_ADDR (__GPIO_BASE + 0xFC )/* [0xFC] */ +#define GPIO_OD_GP62_WAKEUP_SUS_BYTE_ADDR (__GPIO_BASE + 0xFE )/* [0xFE] */ +#define GPIO_OD_GP63_SD02CD_BYTE_ADDR (__GPIO_BASE + 0xFF )/* [0xFF] */ +#define STRAP_STATUS_ADDR (__GPIO_BASE + 0x100 )/* [0x100 ~ 0x103] */ +#define AHB_CTRL_4BYTE_ADDR (__GPIO_BASE + 0x108 )/* [0x108 ~ 0x10B] */ +#define USB_OP_CTRL_4BYTE_ADDR (__GPIO_BASE + 0x10C )/* [0x10C ~ 0x10F] */ +#define BONDING_OPTION_4BYTE_ADDR (__GPIO_BASE + 0x110 )/* [0x110 ~ 0x113] */ +#define PIN_SHARING_SEL_4BYTE_ADDR (__GPIO_BASE + 0x200 )/* [0x200 ~ 0x203] */ +#define TPIU_CLK_DATA_4BYTE_ADDR (__GPIO_BASE + 0x244 )/* [0x244 ~ 0x247] */ +#define GPIO0_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x300 )/* [0x300] */ +#define GPIO1_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x301 )/* [0x301] */ +#define GPIO2_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x302 )/* [0x302] */ +#define GPIO3_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x303 )/* [0x303] */ +#define GPIO4_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x304 )/* [0x304] */ +#define GPIO5_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x305 )/* [0x305] */ +#define GPIO6_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x306 )/* [0x306] */ +#define GPIO7_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x307 )/* [0x307] */ +#define GPIO8_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x308 )/* [0x308] */ +#define GPIO9_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x309 )/* [0x309] */ +#define GPIO10_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x30A )/* [0x30A] */ +#define GPIO11_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x30B )/* [0x30B] */ +#define GPIO12_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x30C )/* [0x30C] */ +#define GPIO13_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x30D )/* [0x30D] */ +#define GPIO18_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x30E )/* [0x30E] */ +#define GPIO19_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x30F )/* [0x30F] */ +#define VOUT20_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x310 )/* [0x310] */ +#define VOUT21_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x311 )/* [0x311] */ +#define VOUT22_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x312 )/* [0x312] */ +#define VOUT23_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x313 )/* [0x313] */ +#define GPIO20_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x314 )/* [0x314] */ +#define GPIO21_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x315 )/* [0x315] */ +#define GPIO22_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x316 )/* [0x316] */ +#define GPIO23_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x317 )/* [0x317] */ +#define GPIO24_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x318 )/* [0x318] */ +#define GPIO25_INT_REQ_TYPE_ADDR (__GPIO_BASE + 0x319 )/* [0x319] */ +#define GPIO0_INT_REQ_STS_ADDR (__GPIO_BASE + 0x360 )/* [0x360] */ +#define GPIO1_INT_REQ_STS_ADDR (__GPIO_BASE + 0x361 )/* [0x361] */ +#define GPIO2_INT_REQ_STS_ADDR (__GPIO_BASE + 0x362 )/* [0x362] */ +#define GPIO3_INT_REQ_STS_ADDR (__GPIO_BASE + 0x363 )/* [0x363] */ +#define DRV_DVO_CLK_BYTE_ADDR (__GPIO_BASE + 0x402 )/* [0x402] */ +#define DRV_DVO_VDEN_BYTE_ADDR (__GPIO_BASE + 0x403 )/* [0x403] */ +#define SD0_DPCTL_4BYTE_ADDR (__GPIO_BASE + 0x404 )/* [0x404 ~ 0x407] */ +#define SD0_DNCTL_4BYTE_ADDR (__GPIO_BASE + 0x408 )/* [0x408 ~ 0x40B] */ +#define DRV_SD0_USB_BYTE_ADDR (__GPIO_BASE + 0x464 )/* [0x464] */ +#define DRV_USB_SWOC0_BYTE_ADDR (__GPIO_BASE + 0x465 )/* [0x465] */ +#define DRV_USB_OC12_BYTE_ADDR (__GPIO_BASE + 0x466 )/* [0x466] */ +#define DRV_USBOC3_CIR_BYTE_ADDR (__GPIO_BASE + 0x467 )/* [0x467] */ +#define DRV_PWREN_BYTE_ADDR (__GPIO_BASE + 0x468 )/* [0x468] */ +#define DRV_PWREN_WAKEUP0_BYTE_ADDR (__GPIO_BASE + 0x469 )/* [0x469] */ +#define DRV_SUSGP01_BYTE_ADDR (__GPIO_BASE + 0x46A )/* [0x46A] */ +#define DRV_WAKEUP23_BYTE_ADDR (__GPIO_BASE + 0x46B )/* [0x46B] */ +#define DRV_WAKEUP45_BYTE_ADDR (__GPIO_BASE + 0x46C )/* [0x46C] */ +#define DRV_I2C_BYTE_ADDR (__GPIO_BASE + 0x46D )/* [0x46D] */ +#define DRV_HDMI_BYTE_ADDR (__GPIO_BASE + 0x46E )/* [0x46E] */ +#define PULL_EN_GP0_BYTE_ADDR (__GPIO_BASE + 0x480 )/* [0x480] */ +#define PULL_EN_GP1_BYTE_ADDR (__GPIO_BASE + 0x481 )/* [0x481] */ +#define PULL_EN_GP2_BYTE_ADDR (__GPIO_BASE + 0x482 )/* [0x482] */ +#define PULL_EN_GP4_VDOUT_7_0_BYTE_ADDR (__GPIO_BASE + 0x484 )/* [0x484] */ +#define PULL_EN_GP5_VDOUT_15_8_BYTE_ADDR (__GPIO_BASE + 0x485 )/* [0x485] */ +#define PULL_EN_GP6_VDOUT_23_16_BYTE_ADDR (__GPIO_BASE + 0x486 )/* [0x486] */ +#define PULL_EN_GP7_VD_BYTE_ADDR (__GPIO_BASE + 0x487 )/* [0x487] */ +#define PULL_EN_GP8_VDIN_BYTE_ADDR (__GPIO_BASE + 0x488 )/* [0x488] */ +#define PULL_EN_GP9_VSYNC_BYTE_ADDR (__GPIO_BASE + 0x489 )/* [0x489] */ +#define PULL_EN_GP10_I2S_BYTE_ADDR (__GPIO_BASE + 0x48A )/* [0x48A] */ +#define PULL_EN_GP11_I2S_BYTE_ADDR (__GPIO_BASE + 0x48B )/* [0x48B] */ +#define PULL_EN_GP12_SPI_BYTE_ADDR (__GPIO_BASE + 0x48C )/* [0x48C] */ +#define PULL_EN_GP13_SD0_BYTE_ADDR (__GPIO_BASE + 0x48D )/* [0x48D] */ +#define PULL_EN_GP14_NAND_BYTE_ADDR (__GPIO_BASE + 0x48E )/* [0x48E] */ +#define PULL_EN_GP15_NAND_BYTE_ADDR (__GPIO_BASE + 0x48F )/* [0x48F] */ +#define PULL_EN_GP16_NANDIO_BYTE_ADDR (__GPIO_BASE + 0x490 )/* [0x490] */ +#define PULL_EN_GP17_I2C_BYTE_ADDR (__GPIO_BASE + 0x491 )/* [0x491] */ +#define PULL_EN_GP18_UART_BYTE_ADDR (__GPIO_BASE + 0x492 )/* [0x492] */ +#define PULL_EN_GP19_SD2_BYTE_ADDR (__GPIO_BASE + 0x493 )/* [0x493] */ +#define PULL_EN_GP20_PWM0_BYTE_ADDR (__GPIO_BASE + 0x494 )/* [0x494] */ +#define PULL_EN_GP21_HDMI_BYTE_ADDR (__GPIO_BASE + 0x495 )/* [0x495] */ +#define PULL_EN_GP23_I2C3_BYTE_ADDR (__GPIO_BASE + 0x497 )/* [0x497] */ +#define PULL_EN_GP24_SF_BYTE_ADDR (__GPIO_BASE + 0x498 )/* [0x498] */ +#define PULL_EN_GP26_PCM_BYTE_ADDR (__GPIO_BASE + 0x49A )/* [0x49A] */ +#define PULL_EN_GP60_USB_BYTE_ADDR (__GPIO_BASE + 0x4BC )/* [0x4BC] */ +#define PULL_EN_GP62_WAKEUP_SUS_BYTE_ADDR (__GPIO_BASE + 0x4BE )/* [0x4BE] */ +#define PULL_EN_GP63_SD02_BYTE_ADDR (__GPIO_BASE + 0x4BF )/* [0x4BF] */ +#define PULL_CTRL_GP0_BYTE_ADDR (__GPIO_BASE + 0x4C0 )/* [0x4C0] */ +#define PULL_CTRL_GP1_BYTE_ADDR (__GPIO_BASE + 0x4C1 )/* [0x4C1] */ +#define PULL_CTRL_GP2_BYTE_ADDR (__GPIO_BASE + 0x4C2 )/* [0x4C2] */ +#define PULL_CTRL_GP4_VDOUT_7_0_BYTE_ADDR (__GPIO_BASE + 0x4C4 )/* [0x4C4] */ +#define PULL_CTRL_GP5_VDOUT_15_8_BYTE_ADDR (__GPIO_BASE + 0x4C5 )/* [0x4C5] */ +#define PULL_CTRL_GP6_VDOUT_23_16_BYTE_ADDR (__GPIO_BASE + 0x4C6 )/* [0x4C6] */ +#define PULL_CTRL_GP7_VD_BYTE_ADDR (__GPIO_BASE + 0x4C7 )/* [0x4C7] */ +#define PULL_CTRL_GP8_VDIN_BYTE_ADDR (__GPIO_BASE + 0x4C8 )/* [0x4C8] */ +#define PULL_CTRL_GP9_VSYNC_BYTE_ADDR (__GPIO_BASE + 0x4C9 )/* [0x4C9] */ +#define PULL_CTRL_GP10_I2S_BYTE_ADDR (__GPIO_BASE + 0x4CA )/* [0x4CA] */ +#define PULL_CTRL_GP11_I2S_BYTE_ADDR (__GPIO_BASE + 0x4CB )/* [0x4CB] */ +#define PULL_CTRL_GP12_SPI_BYTE_ADDR (__GPIO_BASE + 0x4CC )/* [0x4CC] */ +#define PULL_CTRL_GP13_SD0_BYTE_ADDR (__GPIO_BASE + 0x4CD )/* [0x4CD] */ +#define PULL_CTRL_GP14_NAND_BYTE_ADDR (__GPIO_BASE + 0x4CE )/* [0x4CE] */ +#define PULL_CTRL_GP15_NAND_BYTE_ADDR (__GPIO_BASE + 0x4CF )/* [0x4CF] */ +#define PULL_CTRL_GP16_NANDIO_BYTE_ADDR (__GPIO_BASE + 0x4D0 )/* [0x4D0] */ +#define PULL_CTRL_GP17_I2C_BYTE_ADDR (__GPIO_BASE + 0x4D1 )/* [0x4D1] */ +#define PULL_CTRL_GP18_UART_BYTE_ADDR (__GPIO_BASE + 0x4D2 )/* [0x4D2] */ +#define PULL_CTRL_GP19_SD2_BYTE_ADDR (__GPIO_BASE + 0x4D3 )/* [0x4D3] */ +#define PULL_CTRL_GP20_PWM0_BYTE_ADDR (__GPIO_BASE + 0x4D4 )/* [0x4D4] */ +#define PULL_CTRL_GP21_HDMI_BYTE_ADDR (__GPIO_BASE + 0x4D5 )/* [0x4D5] */ +#define PULL_CTRL_GP23_I2C3_BYTE_ADDR (__GPIO_BASE + 0x4D7 )/* [0x4D7] */ +#define PULL_CTRL_GP24_SF_BYTE_ADDR (__GPIO_BASE + 0x4D8 )/* [0x4D8] */ +#define PULL_CTRL_GP26_PCM_BYTE_ADDR (__GPIO_BASE + 0x4DA )/* [0x4DA] */ +#define PULL_CTRL_GP27_SD0_BYTE_ADDR (__GPIO_BASE + 0x4DB )/* [0x4DB] */ +#define PULL_CTRL_GP60_USB_BYTE_ADDR (__GPIO_BASE + 0x4FC )/* [0x4FC] */ +#define PULL_CTRL_GP62_WAKEUP_SUS_BYTE_ADDR (__GPIO_BASE + 0x4FE )/* [0x4FE] */ +#define PULL_CTRL_GP63_SD02_BYTE_ADDR (__GPIO_BASE + 0x4FF )/* [0x4FF] */ +#define DRV_GPIO_7_0_4BYTE_ADDR (__GPIO_BASE + 0x800 )/* [0x800 ~ 0x803] */ +#define DRV_GPIO_13_8_4BYTE_ADDR (__GPIO_BASE + 0x804 )/* [0x804 ~ 0x807] */ +#define DRV_GPIO_19_14_4BYTE_ADDR (__GPIO_BASE + 0x808 )/* [0x808 ~ 0x80B] */ +#define DRV_VDIN_3_0_4BYTE_ADDR (__GPIO_BASE + 0x80C )/* [0x80C ~ 0x80F] */ +#define DRV_VDIN_4_6_4BYTE_ADDR (__GPIO_BASE + 0x810 )/* [0x810 ~ 0x813] */ +#define DRV_VDIN_SPI_4BYTE_ADDR (__GPIO_BASE + 0x814 )/* [0x814 ~ 0x817] */ +#define DRV_SPI_NAND_4BYTE_ADDR (__GPIO_BASE + 0x818 )/* [0x818 ~ 0x81B] */ +#define DRV_NAND_4BYTE_ADDR (__GPIO_BASE + 0x81C )/* [0x81C ~ 0x81F] */ +#define DRV_NANDIO_4BYTE_ADDR (__GPIO_BASE + 0x820 )/* [0x820 ~ 0x823] */ +#define DRV_HDMI_I2C_4BYTE_ADDR (__GPIO_BASE + 0x824 )/* [0x824 ~ 0x827] */ +#define DRV_I2C_SD0_4BYTE_ADDR (__GPIO_BASE + 0x828 )/* [0x828 ~ 0x82B] */ +#define DRV_SD0_SD2_4BYTE_ADDR (__GPIO_BASE + 0x82C )/* [0x82C ~ 0x82F] */ +#define DRV_SD2_I2S_4BYTE_ADDR (__GPIO_BASE + 0x830 )/* [0x830 ~ 0x833] */ +#define DRV_I2S_UART_4BYTE_ADDR (__GPIO_BASE + 0x834 )/* [0x834 ~ 0x837] */ +#define DRV_UART_4BYTE_ADDR (__GPIO_BASE + 0x838 )/* [0x838 ~ 0x83B] */ +#define DRV_SF_JTAGT_4BYTE_ADDR (__GPIO_BASE + 0x83C )/* [0x83C ~ 0x83F] */ +#define DRV_JTAGT_PWM_4BYTE_ADDR (__GPIO_BASE + 0x840 )/* [0x840 ~ 0x843] */ +#define DRV_PCM_BYTE_ADDR (__GPIO_BASE + 0x844 )/* [0x844] */ +#define DRV_SPI_BYTE_ADDR (__GPIO_BASE + 0x84C )/* [0x84C] */ + + + +#define GPIO_ID_GP0_BYTE_REG REG8_PTR(GPIO_ID_GP0_BYTE_ADDR ) +#define GPIO_ID_GP1_BYTE_REG REG8_PTR(GPIO_ID_GP1_BYTE_ADDR ) +#define GPIO_ID_GP2_BYTE_REG REG8_PTR(GPIO_ID_GP2_BYTE_ADDR ) +#define GPIO_ID_GP4_VDOUT_7_0_BYTE_REG REG8_PTR(GPIO_ID_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_ID_GP5_VDOUT_15_8_BYTE_REG REG8_PTR(GPIO_ID_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_ID_GP6_VDOUT_23_16_BYTE_REG REG8_PTR(GPIO_ID_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_ID_GP7_VD_BYTE_REG REG8_PTR(GPIO_ID_GP7_VD_BYTE_ADDR ) +#define GPIO_ID_GP8_VDIN_BYTE_REG REG8_PTR(GPIO_ID_GP8_VDIN_BYTE_ADDR ) +#define GPIO_ID_GP9_VSYNC_BYTE_REG REG8_PTR(GPIO_ID_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_ID_GP10_I2S_BYTE_REG REG8_PTR(GPIO_ID_GP10_I2S_BYTE_ADDR ) +#define GPIO_ID_GP11_I2S_BYTE_REG REG8_PTR(GPIO_ID_GP11_I2S_BYTE_ADDR ) +#define GPIO_ID_GP12_SPI_BYTE_REG REG8_PTR(GPIO_ID_GP12_SPI_BYTE_ADDR ) +#define GPIO_ID_GP13_SD0_BYTE_REG REG8_PTR(GPIO_ID_GP13_SD0_BYTE_ADDR ) +#define GPIO_ID_GP14_NAND_SD1_BYTE_REG REG8_PTR(GPIO_ID_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_ID_GP15_NAND_BYTE_REG REG8_PTR(GPIO_ID_GP15_NAND_BYTE_ADDR ) +#define GPIO_ID_GP16_NAND_SD1_BYTE_REG REG8_PTR(GPIO_ID_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_ID_GP17_I2C_BYTE_REG REG8_PTR(GPIO_ID_GP17_I2C_BYTE_ADDR ) +#define GPIO_ID_GP18_UART_BYTE_REG REG8_PTR(GPIO_ID_GP18_UART_BYTE_ADDR ) +#define GPIO_ID_GP19_SD2_BYTE_REG REG8_PTR(GPIO_ID_GP19_SD2_BYTE_ADDR ) +#define GPIO_ID_GP20_PWM0_BYTE_REG REG8_PTR(GPIO_ID_GP20_PWM0_BYTE_ADDR ) +#define GPIO_ID_GP21_HDMI_BYTE_REG REG8_PTR(GPIO_ID_GP21_HDMI_BYTE_ADDR ) +#define GPIO_ID_GP23_I2C3_BYTE_REG REG8_PTR(GPIO_ID_GP23_I2C3_BYTE_ADDR ) +#define GPIO_ID_GP24_SF_BYTE_REG REG8_PTR(GPIO_ID_GP24_SF_BYTE_ADDR ) +#define GPIO_ID_GP26_PCM_BYTE_REG REG8_PTR(GPIO_ID_GP26_PCM_BYTE_ADDR ) +#define GPIO_ID_GP60_USB_BYTE_REG REG8_PTR(GPIO_ID_GP60_USB_BYTE_ADDR ) +#define GPIO_ID_GP62_WAKEUP_SUS_BYTE_REG REG8_PTR(GPIO_ID_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_ID_GP63_SD02CD_BYTE_REG REG8_PTR(GPIO_ID_GP63_SD02CD_BYTE_ADDR ) +#define GPIO_CTRL_GP0_BYTE_REG REG8_PTR(GPIO_CTRL_GP0_BYTE_ADDR ) +#define GPIO_CTRL_GP1_BYTE_REG REG8_PTR(GPIO_CTRL_GP1_BYTE_ADDR ) +#define GPIO_CTRL_GP2_BYTE_REG REG8_PTR(GPIO_CTRL_GP2_BYTE_ADDR ) +#define GPIO_CTRL_GP4_VDOUT_7_0_BYTE_REG REG8_PTR(GPIO_CTRL_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_CTRL_GP5_VDOUT_15_8_BYTE_REG REG8_PTR(GPIO_CTRL_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_CTRL_GP6_VDOUT_23_16_BYTE_REG REG8_PTR(GPIO_CTRL_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_CTRL_GP7_VD_BYTE_REG REG8_PTR(GPIO_CTRL_GP7_VD_BYTE_ADDR ) +#define GPIO_CTRL_GP8_VDIN_BYTE_REG REG8_PTR(GPIO_CTRL_GP8_VDIN_BYTE_ADDR ) +#define GPIO_CTRL_GP9_VSYNC_BYTE_REG REG8_PTR(GPIO_CTRL_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_CTRL_GP10_I2S_BYTE_REG REG8_PTR(GPIO_CTRL_GP10_I2S_BYTE_ADDR ) +#define GPIO_CTRL_GP11_I2S_BYTE_REG REG8_PTR(GPIO_CTRL_GP11_I2S_BYTE_ADDR ) +#define GPIO_CTRL_GP12_SPI_BYTE_REG REG8_PTR(GPIO_CTRL_GP12_SPI_BYTE_ADDR ) +#define GPIO_CTRL_GP13_SD0_BYTE_REG REG8_PTR(GPIO_CTRL_GP13_SD0_BYTE_ADDR ) +#define GPIO_CTRL_GP14_NAND_SD1_BYTE_REG REG8_PTR(GPIO_CTRL_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_CTRL_GP15_NAND_BYTE_REG REG8_PTR(GPIO_CTRL_GP15_NAND_BYTE_ADDR ) +#define GPIO_CTRL_GP16_NAND_SD1_BYTE_REG REG8_PTR(GPIO_CTRL_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_CTRL_GP17_I2C_BYTE_REG REG8_PTR(GPIO_CTRL_GP17_I2C_BYTE_ADDR ) +#define GPIO_CTRL_GP18_UART_BYTE_REG REG8_PTR(GPIO_CTRL_GP18_UART_BYTE_ADDR ) +#define GPIO_CTRL_GP19_SD2_BYTE_REG REG8_PTR(GPIO_CTRL_GP19_SD2_BYTE_ADDR ) +#define GPIO_CTRL_GP20_PWM0_BYTE_REG REG8_PTR(GPIO_CTRL_GP20_PWM0_BYTE_ADDR ) +#define GPIO_CTRL_GP21_HDMI_BYTE_REG REG8_PTR(GPIO_CTRL_GP21_HDMI_BYTE_ADDR ) +#define GPIO_CTRL_GP23_I2C3_BYTE_REG REG8_PTR(GPIO_CTRL_GP23_I2C3_BYTE_ADDR ) +#define GPIO_CTRL_GP24_SF_BYTE_REG REG8_PTR(GPIO_CTRL_GP24_SF_BYTE_ADDR ) +#define GPIO_CTRL_GP26_PCM_BYTE_REG REG8_PTR(GPIO_CTRL_GP26_PCM_BYTE_ADDR ) +#define GPIO_CTRL_GP60_USB_BYTE_REG REG8_PTR(GPIO_CTRL_GP60_USB_BYTE_ADDR ) +#define GPIO_CTRL_GP62_WAKEUP_SUS_BYTE_REG REG8_PTR(GPIO_CTRL_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_CTRL_GP63_SD02CD_BYTE_REG REG8_PTR(GPIO_CTRL_GP63_SD02CD_BYTE_ADDR ) +#define GPIO_OC_GP0_BYTE_REG REG8_PTR(GPIO_OC_GP0_BYTE_ADDR ) +#define GPIO_OC_GP1_BYTE_REG REG8_PTR(GPIO_OC_GP1_BYTE_ADDR ) +#define GPIO_OC_GP2_BYTE_REG REG8_PTR(GPIO_OC_GP2_BYTE_ADDR ) +#define GPIO_OC_GP4_VDOUT_7_0_BYTE_REG REG8_PTR(GPIO_OC_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_OC_GP5_VDOUT_15_8_BYTE_REG REG8_PTR(GPIO_OC_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_OC_GP6_VDOUT_23_16_BYTE_REG REG8_PTR(GPIO_OC_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_OC_GP7_VD_BYTE_REG REG8_PTR(GPIO_OC_GP7_VD_BYTE_ADDR ) +#define GPIO_OC_GP8_VDIN_BYTE_REG REG8_PTR(GPIO_OC_GP8_VDIN_BYTE_ADDR ) +#define GPIO_OC_GP9_VSYNC_BYTE_REG REG8_PTR(GPIO_OC_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_OC_GP10_I2S_BYTE_REG REG8_PTR(GPIO_OC_GP10_I2S_BYTE_ADDR ) +#define GPIO_OC_GP11_I2S_BYTE_REG REG8_PTR(GPIO_OC_GP11_I2S_BYTE_ADDR ) +#define GPIO_OC_GP12_SPI_BYTE_REG REG8_PTR(GPIO_OC_GP12_SPI_BYTE_ADDR ) +#define GPIO_OC_GP13_SD0_BYTE_REG REG8_PTR(GPIO_OC_GP13_SD0_BYTE_ADDR ) +#define GPIO_OC_GP14_NAND_SD1_BYTE_REG REG8_PTR(GPIO_OC_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_OC_GP15_NAND_BYTE_REG REG8_PTR(GPIO_OC_GP15_NAND_BYTE_ADDR ) +#define GPIO_OC_GP16_NAND_SD1_BYTE_REG REG8_PTR(GPIO_OC_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_OC_GP17_I2C_BYTE_REG REG8_PTR(GPIO_OC_GP17_I2C_BYTE_ADDR ) +#define GPIO_OC_GP18_UART_BYTE_REG REG8_PTR(GPIO_OC_GP18_UART_BYTE_ADDR ) +#define GPIO_OC_GP19_SD2_BYTE_REG REG8_PTR(GPIO_OC_GP19_SD2_BYTE_ADDR ) +#define GPIO_OC_GP20_PWM0_BYTE_REG REG8_PTR(GPIO_OC_GP20_PWM0_BYTE_ADDR ) +#define GPIO_OC_GP21_HDMI_BYTE_REG REG8_PTR(GPIO_OC_GP21_HDMI_BYTE_ADDR ) +#define GPIO_OC_GP22_I2C3_BYTE_REG REG8_PTR(GPIO_OC_GP22_I2C3_BYTE_ADDR ) +#define GPIO_OC_GP24_SF_BYTE_REG REG8_PTR(GPIO_OC_GP24_SF_BYTE_ADDR ) +#define GPIO_OC_GP26_PCM_BYTE_REG REG8_PTR(GPIO_OC_GP26_PCM_BYTE_ADDR ) +#define GPIO_OC_GP60_USB_BYTE_REG REG8_PTR(GPIO_OC_GP60_USB_BYTE_ADDR ) +#define GPIO_OC_GP62_WAKEUP_SUS_BYTE_REG REG8_PTR(GPIO_OC_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_OC_GP63_SD02CD_BYTE_REG REG8_PTR(GPIO_OC_GP63_SD02CD_BYTE_ADDR ) +#define GPIO_OD_GP0_BYTE_REG REG8_PTR(GPIO_OD_GP0_BYTE_ADDR ) +#define GPIO_OD_GP1_BYTE_REG REG8_PTR(GPIO_OD_GP1_BYTE_ADDR ) +#define GPIO_OD_GP2_BYTE_REG REG8_PTR(GPIO_OD_GP2_BYTE_ADDR ) +#define GPIO_OD_GP4_VDOUT_7_0_BYTE_REG REG8_PTR(GPIO_OD_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_OD_GP5_VDOUT_15_8_BYTE_REG REG8_PTR(GPIO_OD_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_OD_GP6_VDOUT_23_16_BYTE_REG REG8_PTR(GPIO_OD_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_OD_GP7_VD_BYTE_REG REG8_PTR(GPIO_OD_GP7_VD_BYTE_ADDR ) +#define GPIO_OD_GP8_VDIN_BYTE_REG REG8_PTR(GPIO_OD_GP8_VDIN_BYTE_ADDR ) +#define GPIO_OD_GP9_VSYNC_BYTE_REG REG8_PTR(GPIO_OD_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_OD_GP10_I2S_BYTE_REG REG8_PTR(GPIO_OD_GP10_I2S_BYTE_ADDR ) +#define GPIO_OD_GP11_I2S_BYTE_REG REG8_PTR(GPIO_OD_GP11_I2S_BYTE_ADDR ) +#define GPIO_OD_GP12_SPI_BYTE_REG REG8_PTR(GPIO_OD_GP12_SPI_BYTE_ADDR ) +#define GPIO_OD_GP13_SD0_BYTE_REG REG8_PTR(GPIO_OD_GP13_SD0_BYTE_ADDR ) +#define GPIO_OD_GP14_NAND_SD1_BYTE_REG REG8_PTR(GPIO_OD_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_OD_GP15_NAND_BYTE_REG REG8_PTR(GPIO_OD_GP15_NAND_BYTE_ADDR ) +#define GPIO_OD_GP16_NAND_SD1_BYTE_REG REG8_PTR(GPIO_OD_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_OD_GP17_I2C_BYTE_REG REG8_PTR(GPIO_OD_GP17_I2C_BYTE_ADDR ) +#define GPIO_OD_GP18_UART_BYTE_REG REG8_PTR(GPIO_OD_GP18_UART_BYTE_ADDR ) +#define GPIO_OD_GP19_SD2_BYTE_REG REG8_PTR(GPIO_OD_GP19_SD2_BYTE_ADDR ) +#define GPIO_OD_GP20_PWM0_BYTE_REG REG8_PTR(GPIO_OD_GP20_PWM0_BYTE_ADDR ) +#define GPIO_OD_GP21_HDMI_BYTE_REG REG8_PTR(GPIO_OD_GP21_HDMI_BYTE_ADDR ) +#define GPIO_OD_GP23_I2C3_BYTE_REG REG8_PTR(GPIO_OD_GP23_I2C3_BYTE_ADDR ) +#define GPIO_OD_GP24_SF_BYTE_REG REG8_PTR(GPIO_OD_GP24_SF_BYTE_ADDR ) +#define GPIO_OD_GP26_PCM_BYTE_REG REG8_PTR(GPIO_OD_GP26_PCM_BYTE_ADDR ) +#define GPIO_OD_GP60_USB_BYTE_REG REG8_PTR(GPIO_OD_GP60_USB_BYTE_ADDR ) +#define GPIO_OD_GP62_WAKEUP_SUS_BYTE_REG REG8_PTR(GPIO_OD_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_OD_GP63_SD02CD_BYTE_REG REG8_PTR(GPIO_OD_GP63_SD02CD_BYTE_ADDR ) +#define STRAP_STATUS_REG REG32_PTR(STRAP_STATUS_ADDR ) +#define AHB_CTRL_4BYTE_REG REG32_PTR(AHB_CTRL_4BYTE_ADDR ) +#define USB_OP_CTRL_4BYTE_REG REG32_PTR(USB_OP_CTRL_4BYTE_ADDR ) +#define BONDING_OPTION_4BYTE_REG REG32_PTR(BONDING_OPTION_4BYTE_ADDR ) +#define PIN_SHARING_SEL_4BYTE_REG REG32_PTR(PIN_SHARING_SEL_4BYTE_ADDR ) +#define TPIU_CLK_DATA_4BYTE_REG REG32_PTR(TPIU_CLK_DATA_4BYTE_ADDR ) +#define GPIO0_INT_REQ_TYPE_REG REG8_PTR(GPIO0_INT_REQ_TYPE_ADDR ) +#define GPIO1_INT_REQ_TYPE_REG REG8_PTR(GPIO1_INT_REQ_TYPE_ADDR ) +#define GPIO2_INT_REQ_TYPE_REG REG8_PTR(GPIO2_INT_REQ_TYPE_ADDR ) +#define GPIO3_INT_REQ_TYPE_REG REG8_PTR(GPIO3_INT_REQ_TYPE_ADDR ) +#define GPIO4_INT_REQ_TYPE_REG REG8_PTR(GPIO4_INT_REQ_TYPE_ADDR ) +#define GPIO5_INT_REQ_TYPE_REG REG8_PTR(GPIO5_INT_REQ_TYPE_ADDR ) +#define GPIO6_INT_REQ_TYPE_REG REG8_PTR(GPIO6_INT_REQ_TYPE_ADDR ) +#define GPIO7_INT_REQ_TYPE_REG REG8_PTR(GPIO7_INT_REQ_TYPE_ADDR ) +#define GPIO8_INT_REQ_TYPE_REG REG8_PTR(GPIO8_INT_REQ_TYPE_ADDR ) +#define GPIO9_INT_REQ_TYPE_REG REG8_PTR(GPIO9_INT_REQ_TYPE_ADDR ) +#define GPIO10_INT_REQ_TYPE_REG REG8_PTR(GPIO10_INT_REQ_TYPE_ADDR ) +#define GPIO11_INT_REQ_TYPE_REG REG8_PTR(GPIO11_INT_REQ_TYPE_ADDR ) +#define GPIO12_INT_REQ_TYPE_REG REG8_PTR(GPIO12_INT_REQ_TYPE_ADDR ) +#define GPIO13_INT_REQ_TYPE_REG REG8_PTR(GPIO13_INT_REQ_TYPE_ADDR ) +#define GPIO18_INT_REQ_TYPE_REG REG8_PTR(GPIO18_INT_REQ_TYPE_ADDR ) +#define GPIO19_INT_REQ_TYPE_REG REG8_PTR(GPIO19_INT_REQ_TYPE_ADDR ) +#define VOUT20_INT_REQ_TYPE_REG REG8_PTR(VOUT20_INT_REQ_TYPE_ADDR ) +#define VOUT21_INT_REQ_TYPE_REG REG8_PTR(VOUT21_INT_REQ_TYPE_ADDR ) +#define VOUT22_INT_REQ_TYPE_REG REG8_PTR(VOUT22_INT_REQ_TYPE_ADDR ) +#define VOUT23_INT_REQ_TYPE_REG REG8_PTR(VOUT23_INT_REQ_TYPE_ADDR ) +#define GPIO20_INT_REQ_TYPE_REG REG8_PTR(GPIO20_INT_REQ_TYPE_ADDR ) +#define GPIO21_INT_REQ_TYPE_REG REG8_PTR(GPIO21_INT_REQ_TYPE_ADDR ) +#define GPIO22_INT_REQ_TYPE_REG REG8_PTR(GPIO22_INT_REQ_TYPE_ADDR ) +#define GPIO23_INT_REQ_TYPE_REG REG8_PTR(GPIO23_INT_REQ_TYPE_ADDR ) +#define GPIO24_INT_REQ_TYPE_REG REG8_PTR(GPIO24_INT_REQ_TYPE_ADDR ) +#define GPIO25_INT_REQ_TYPE_REG REG8_PTR(GPIO25_INT_REQ_TYPE_ADDR ) +#define GPIO0_INT_REQ_STS_REG REG8_PTR(GPIO0_INT_REQ_STS_ADDR ) +#define GPIO1_INT_REQ_STS_REG REG8_PTR(GPIO1_INT_REQ_STS_ADDR ) +#define GPIO2_INT_REQ_STS_REG REG8_PTR(GPIO2_INT_REQ_STS_ADDR ) +#define GPIO3_INT_REQ_STS_REG REG8_PTR(GPIO3_INT_REQ_STS_ADDR ) +#define DRV_DVO_CLK_BYTE_REG REG8_PTR(DRV_DVO_CLK_BYTE_ADDR ) +#define DRV_DVO_VDEN_BYTE_REG REG8_PTR(DRV_DVO_VDEN_BYTE_ADDR ) +#define SD0_DPCTL_4BYTE_REG REG32_PTR(SD0_DPCTL_4BYTE_ADDR ) +#define SD0_DNCTL_4BYTE_REG REG32_PTR(SD0_DNCTL_4BYTE_ADDR ) +#define DRV_SD0_USB_BYTE_REG REG8_PTR(DRV_SD0_USB_BYTE_ADDR ) +#define DRV_USB_SWOC0_BYTE_REG REG8_PTR(DRV_USB_SWOC0_BYTE_ADDR ) +#define DRV_USB_OC12_BYTE_REG REG8_PTR(DRV_USB_OC12_BYTE_ADDR ) +#define DRV_USBOC3_CIR_BYTE_REG REG8_PTR(DRV_USBOC3_CIR_BYTE_ADDR ) +#define DRV_PWREN_BYTE_REG REG8_PTR(DRV_PWREN_BYTE_ADDR ) +#define DRV_PWREN_WAKEUP0_BYTE_REG REG8_PTR(DRV_PWREN_WAKEUP0_BYTE_ADDR ) +#define DRV_SUSGP01_BYTE_REG REG8_PTR(DRV_SUSGP01_BYTE_ADDR ) +#define DRV_WAKEUP23_BYTE_REG REG8_PTR(DRV_WAKEUP23_BYTE_ADDR ) +#define DRV_WAKEUP45_BYTE_REG REG8_PTR(DRV_WAKEUP45_BYTE_ADDR ) +#define DRV_I2C_BYTE_REG REG8_PTR(DRV_I2C_BYTE_ADDR ) +#define DRV_HDMI_BYTE_REG REG8_PTR(DRV_HDMI_BYTE_ADDR ) +#define PULL_EN_GP0_BYTE_REG REG8_PTR(PULL_EN_GP0_BYTE_ADDR ) +#define PULL_EN_GP1_BYTE_REG REG8_PTR(PULL_EN_GP1_BYTE_ADDR ) +#define PULL_EN_GP2_BYTE_REG REG8_PTR(PULL_EN_GP2_BYTE_ADDR ) +#define PULL_EN_GP4_VDOUT_7_0_BYTE_REG REG8_PTR(PULL_EN_GP4_VDOUT_7_0_BYTE_ADDR ) +#define PULL_EN_GP5_VDOUT_15_8_BYTE_REG REG8_PTR(PULL_EN_GP5_VDOUT_15_8_BYTE_ADDR ) +#define PULL_EN_GP6_VDOUT_23_16_BYTE_REG REG8_PTR(PULL_EN_GP6_VDOUT_23_16_BYTE_ADDR ) +#define PULL_EN_GP7_VD_BYTE_REG REG8_PTR(PULL_EN_GP7_VD_BYTE_ADDR ) +#define PULL_EN_GP8_VDIN_BYTE_REG REG8_PTR(PULL_EN_GP8_VDIN_BYTE_ADDR ) +#define PULL_EN_GP9_VSYNC_BYTE_REG REG8_PTR(PULL_EN_GP9_VSYNC_BYTE_ADDR ) +#define PULL_EN_GP10_I2S_BYTE_REG REG8_PTR(PULL_EN_GP10_I2S_BYTE_ADDR ) +#define PULL_EN_GP11_I2S_BYTE_REG REG8_PTR(PULL_EN_GP11_I2S_BYTE_ADDR ) +#define PULL_EN_GP12_SPI_BYTE_REG REG8_PTR(PULL_EN_GP12_SPI_BYTE_ADDR ) +#define PULL_EN_GP13_SD0_BYTE_REG REG8_PTR(PULL_EN_GP13_SD0_BYTE_ADDR ) +#define PULL_EN_GP14_NAND_BYTE_REG REG8_PTR(PULL_EN_GP14_NAND_BYTE_ADDR ) +#define PULL_EN_GP15_NAND_BYTE_REG REG8_PTR(PULL_EN_GP15_NAND_BYTE_ADDR ) +#define PULL_EN_GP16_NANDIO_BYTE_REG REG8_PTR(PULL_EN_GP16_NANDIO_BYTE_ADDR ) +#define PULL_EN_GP17_I2C_BYTE_REG REG8_PTR(PULL_EN_GP17_I2C_BYTE_ADDR ) +#define PULL_EN_GP18_UART_BYTE_REG REG8_PTR(PULL_EN_GP18_UART_BYTE_ADDR ) +#define PULL_EN_GP19_SD2_BYTE_REG REG8_PTR(PULL_EN_GP19_SD2_BYTE_ADDR ) +#define PULL_EN_GP20_PWM0_BYTE_REG REG8_PTR(PULL_EN_GP20_PWM0_BYTE_ADDR ) +#define PULL_EN_GP21_HDMI_BYTE_REG REG8_PTR(PULL_EN_GP21_HDMI_BYTE_ADDR ) +#define PULL_EN_GP23_I2C3_BYTE_REG REG8_PTR(PULL_EN_GP23_I2C3_BYTE_ADDR ) +#define PULL_EN_GP24_SF_BYTE_REG REG8_PTR(PULL_EN_GP24_SF_BYTE_ADDR ) +#define PULL_EN_GP26_PCM_BYTE_REG REG8_PTR(PULL_EN_GP26_PCM_BYTE_ADDR ) +#define PULL_EN_GP60_USB_BYTE_REG REG8_PTR(PULL_EN_GP60_USB_BYTE_ADDR ) +#define PULL_EN_GP62_WAKEUP_SUS_BYTE_REG REG8_PTR(PULL_EN_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define PULL_EN_GP63_SD02_BYTE_REG REG8_PTR(PULL_EN_GP63_SD02_BYTE_ADDR ) +#define PULL_CTRL_GP0_BYTE_REG REG8_PTR(PULL_CTRL_GP0_BYTE_ADDR ) +#define PULL_CTRL_GP1_BYTE_REG REG8_PTR(PULL_CTRL_GP1_BYTE_ADDR ) +#define PULL_CTRL_GP2_BYTE_REG REG8_PTR(PULL_CTRL_GP2_BYTE_ADDR ) +#define PULL_CTRL_GP4_VDOUT_7_0_BYTE_REG REG8_PTR(PULL_CTRL_GP4_VDOUT_7_0_BYTE_ADDR ) +#define PULL_CTRL_GP5_VDOUT_15_8_BYTE_REG REG8_PTR(PULL_CTRL_GP5_VDOUT_15_8_BYTE_ADDR ) +#define PULL_CTRL_GP6_VDOUT_23_16_BYTE_REG REG8_PTR(PULL_CTRL_GP6_VDOUT_23_16_BYTE_ADDR ) +#define PULL_CTRL_GP7_VD_BYTE_REG REG8_PTR(PULL_CTRL_GP7_VD_BYTE_ADDR ) +#define PULL_CTRL_GP8_VDIN_BYTE_REG REG8_PTR(PULL_CTRL_GP8_VDIN_BYTE_ADDR ) +#define PULL_CTRL_GP9_VSYNC_BYTE_REG REG8_PTR(PULL_CTRL_GP9_VSYNC_BYTE_ADDR ) +#define PULL_CTRL_GP10_I2S_BYTE_REG REG8_PTR(PULL_CTRL_GP10_I2S_BYTE_ADDR ) +#define PULL_CTRL_GP11_I2S_BYTE_REG REG8_PTR(PULL_CTRL_GP11_I2S_BYTE_ADDR ) +#define PULL_CTRL_GP12_SPI_BYTE_REG REG8_PTR(PULL_CTRL_GP12_SPI_BYTE_ADDR ) +#define PULL_CTRL_GP13_SD0_BYTE_REG REG8_PTR(PULL_CTRL_GP13_SD0_BYTE_ADDR ) +#define PULL_CTRL_GP14_NAND_BYTE_REG REG8_PTR(PULL_CTRL_GP14_NAND_BYTE_ADDR ) +#define PULL_CTRL_GP15_NAND_BYTE_REG REG8_PTR(PULL_CTRL_GP15_NAND_BYTE_ADDR ) +#define PULL_CTRL_GP16_NANDIO_BYTE_REG REG8_PTR(PULL_CTRL_GP16_NANDIO_BYTE_ADDR ) +#define PULL_CTRL_GP17_I2C_BYTE_REG REG8_PTR(PULL_CTRL_GP17_I2C_BYTE_ADDR ) +#define PULL_CTRL_GP18_UART_BYTE_REG REG8_PTR(PULL_CTRL_GP18_UART_BYTE_ADDR ) +#define PULL_CTRL_GP19_SD2_BYTE_REG REG8_PTR(PULL_CTRL_GP19_SD2_BYTE_ADDR ) +#define PULL_CTRL_GP20_PWM0_BYTE_REG REG8_PTR(PULL_CTRL_GP20_PWM0_BYTE_ADDR ) +#define PULL_CTRL_GP21_HDMI_BYTE_REG REG8_PTR(PULL_CTRL_GP21_HDMI_BYTE_ADDR ) +#define PULL_CTRL_GP23_I2C3_BYTE_REG REG8_PTR(PULL_CTRL_GP23_I2C3_BYTE_ADDR ) +#define PULL_CTRL_GP24_SF_BYTE_REG REG8_PTR(PULL_CTRL_GP24_SF_BYTE_ADDR ) +#define PULL_CTRL_GP26_PCM_BYTE_REG REG8_PTR(PULL_CTRL_GP26_PCM_BYTE_ADDR ) +#define PULL_CTRL_GP27_SD0_BYTE_REG REG8_PTR(PULL_CTRL_GP27_SD0_BYTE_ADDR ) +#define PULL_CTRL_GP60_USB_BYTE_REG REG8_PTR(PULL_CTRL_GP60_USB_BYTE_ADDR ) +#define PULL_CTRL_GP62_WAKEUP_SUS_BYTE_REG REG8_PTR(PULL_CTRL_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define PULL_CTRL_GP63_SD02_BYTE_REG REG8_PTR(PULL_CTRL_GP63_SD02_BYTE_ADDR ) +#define DRV_GPIO_7_0_4BYTE_REG REG32_PTR(DRV_GPIO_7_0_4BYTE_ADDR ) +#define DRV_GPIO_13_8_4BYTE_REG REG32_PTR(DRV_GPIO_13_8_4BYTE_ADDR ) +#define DRV_GPIO_19_14_4BYTE_REG REG32_PTR(DRV_GPIO_19_14_4BYTE_ADDR ) +#define DRV_VDIN_3_0_4BYTE_REG REG32_PTR(DRV_VDIN_3_0_4BYTE_ADDR ) +#define DRV_VDIN_4_6_4BYTE_REG REG32_PTR(DRV_VDIN_3_0_4BYTE_ADDR ) +#define DRV_VDIN_SPI_4BYTE_REG REG32_PTR(DRV_VDIN_SPI_4BYTE_ADDR ) +#define DRV_SPI_NAND_4BYTE_REG REG32_PTR(DRV_SPI_NAND_4BYTE_ADDR ) +#define DRV_NAND_4BYTE_REG REG32_PTR(DRV_NAND_4BYTE_ADDR ) +#define DRV_NANDIO_4BYTE_REG REG32_PTR(DRV_NANDIO_4BYTE_ADDR ) +#define DRV_HDMI_I2C_4BYTE_REG REG32_PTR(DRV_HDMI_I2C_4BYTE_ADDR ) +#define DRV_I2C_SD0_4BYTE_REG REG32_PTR(DRV_I2C_SD0_4BYTE_ADDR ) +#define DRV_SD0_SD2_4BYTE_REG REG32_PTR(DRV_SD0_SD2_4BYTE_ADDR ) +#define DRV_SD2_I2S_4BYTE_REG REG32_PTR(DRV_SD2_I2S_4BYTE_ADDR ) +#define DRV_I2S_UART_4BYTE_REG REG32_PTR(DRV_I2S_UART_4BYTE_ADDR ) +#define DRV_UART_4BYTE_REG REG32_PTR(DRV_UART_4BYTE_ADDR ) +#define DRV_SF_JTAGT_4BYTE_REG REG32_PTR(DRV_SF_JTAGT_4BYTE_ADDR ) +#define DRV_JTAGT_PWM_4BYTE_REG REG32_PTR(DRV_JTAGT_PWM_4BYTE_ADDR ) +#define DRV_PCM_BYTE_REG REG8_PTR(DRV_PCM_BYTE_ADDR ) +#define DRV_SPI_BYTE_REG REG8_PTR(DRV_SPI_BYTE_ADDR ) + +#define GPIO_ID_GP0_BYTE_VAL REG8_VAL(GPIO_ID_GP0_BYTE_ADDR ) +#define GPIO_ID_GP1_BYTE_VAL REG8_VAL(GPIO_ID_GP1_BYTE_ADDR ) +#define GPIO_ID_GP2_BYTE_VAL REG8_VAL(GPIO_ID_GP2_BYTE_ADDR ) +#define GPIO_ID_GP4_VDOUT_7_0_BYTE_VAL REG8_VAL(GPIO_ID_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_ID_GP5_VDOUT_15_8_BYTE_VAL REG8_VAL(GPIO_ID_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_ID_GP6_VDOUT_23_16_BYTE_VAL REG8_VAL(GPIO_ID_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_ID_GP7_VD_BYTE_VAL REG8_VAL(GPIO_ID_GP7_VD_BYTE_ADDR ) +#define GPIO_ID_GP8_VDIN_BYTE_VAL REG8_VAL(GPIO_ID_GP8_VDIN_BYTE_ADDR ) +#define GPIO_ID_GP9_VSYNC_BYTE_VAL REG8_VAL(GPIO_ID_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_ID_GP10_I2S_BYTE_VAL REG8_VAL(GPIO_ID_GP10_I2S_BYTE_ADDR ) +#define GPIO_ID_GP11_I2S_BYTE_VAL REG8_VAL(GPIO_ID_GP11_I2S_BYTE_ADDR ) +#define GPIO_ID_GP12_SPI_BYTE_VAL REG8_VAL(GPIO_ID_GP12_SPI_BYTE_ADDR ) +#define GPIO_ID_GP13_SD0_BYTE_VAL REG8_VAL(GPIO_ID_GP13_SD0_BYTE_ADDR ) +#define GPIO_ID_GP14_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_ID_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_ID_GP15_NAND_BYTE_VAL REG8_VAL(GPIO_ID_GP15_NAND_BYTE_ADDR ) +#define GPIO_ID_GP16_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_ID_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_ID_GP17_I2C_BYTE_VAL REG8_VAL(GPIO_ID_GP17_I2C_BYTE_ADDR ) +#define GPIO_ID_GP18_UART_BYTE_VAL REG8_VAL(GPIO_ID_GP18_UART_BYTE_ADDR ) +#define GPIO_ID_GP19_SD2_BYTE_VAL REG8_VAL(GPIO_ID_GP19_SD2_BYTE_ADDR ) +#define GPIO_ID_GP20_PWM0_BYTE_VAL REG8_VAL(GPIO_ID_GP20_PWM0_BYTE_ADDR ) +#define GPIO_ID_GP21_HDMI_BYTE_VAL REG8_VAL(GPIO_ID_GP21_HDMI_BYTE_ADDR ) +#define GPIO_ID_GP23_I2C3_BYTE_VAL REG8_VAL(GPIO_ID_GP23_I2C3_BYTE_ADDR ) +#define GPIO_ID_GP24_SF_BYTE_VAL REG8_VAL(GPIO_ID_GP24_SF_BYTE_ADDR ) +#define GPIO_ID_GP26_PCM_BYTE_VAL REG8_VAL(GPIO_ID_GP26_PCM_BYTE_ADDR ) +#define GPIO_ID_GP60_USB_BYTE_VAL REG8_VAL(GPIO_ID_GP60_USB_BYTE_ADDR ) +#define GPIO_ID_GP62_WAKEUP_SUS_BYTE_VAL REG8_VAL(GPIO_ID_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_ID_GP63_SD02CD_BYTE_VAL REG8_VAL(GPIO_ID_GP63_SD02CD_BYTE_ADDR ) +#define GPIO_CTRL_GP0_BYTE_VAL REG8_VAL(GPIO_CTRL_GP0_BYTE_ADDR ) +#define GPIO_CTRL_GP1_BYTE_VAL REG8_VAL(GPIO_CTRL_GP1_BYTE_ADDR ) +#define GPIO_CTRL_GP2_BYTE_VAL REG8_VAL(GPIO_CTRL_GP2_BYTE_ADDR ) +#define GPIO_CTRL_GP4_VDOUT_7_0_BYTE_VAL REG8_VAL(GPIO_CTRL_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_CTRL_GP5_VDOUT_15_8_BYTE_VAL REG8_VAL(GPIO_CTRL_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_CTRL_GP6_VDOUT_23_16_BYTE_VAL REG8_VAL(GPIO_CTRL_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_CTRL_GP7_VD_BYTE_VAL REG8_VAL(GPIO_CTRL_GP7_VD_BYTE_ADDR ) +#define GPIO_CTRL_GP8_VDIN_BYTE_VAL REG8_VAL(GPIO_CTRL_GP8_VDIN_BYTE_ADDR ) +#define GPIO_CTRL_GP9_VSYNC_BYTE_VAL REG8_VAL(GPIO_CTRL_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_CTRL_GP10_I2S_BYTE_VAL REG8_VAL(GPIO_CTRL_GP10_I2S_BYTE_ADDR ) +#define GPIO_CTRL_GP11_I2S_BYTE_VAL REG8_VAL(GPIO_CTRL_GP11_I2S_BYTE_ADDR ) +#define GPIO_CTRL_GP12_SPI_BYTE_VAL REG8_VAL(GPIO_CTRL_GP12_SPI_BYTE_ADDR ) +#define GPIO_CTRL_GP13_SD0_BYTE_VAL REG8_VAL(GPIO_CTRL_GP13_SD0_BYTE_ADDR ) +#define GPIO_CTRL_GP14_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_CTRL_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_CTRL_GP15_NAND_BYTE_VAL REG8_VAL(GPIO_CTRL_GP15_NAND_BYTE_ADDR ) +#define GPIO_CTRL_GP16_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_CTRL_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_CTRL_GP17_I2C_BYTE_VAL REG8_VAL(GPIO_CTRL_GP17_I2C_BYTE_ADDR ) +#define GPIO_CTRL_GP18_UART_BYTE_VAL REG8_VAL(GPIO_CTRL_GP18_UART_BYTE_ADDR ) +#define GPIO_CTRL_GP19_SD2_BYTE_VAL REG8_VAL(GPIO_CTRL_GP19_SD2_BYTE_ADDR ) +#define GPIO_CTRL_GP20_PWM0_BYTE_VAL REG8_VAL(GPIO_CTRL_GP20_PWM0_BYTE_ADDR ) +#define GPIO_CTRL_GP21_HDMI_BYTE_VAL REG8_VAL(GPIO_CTRL_GP21_HDMI_BYTE_ADDR ) +#define GPIO_CTRL_GP23_I2C3_BYTE_VAL REG8_VAL(GPIO_CTRL_GP23_I2C3_BYTE_ADDR ) +#define GPIO_CTRL_GP24_SF_BYTE_VAL REG8_VAL(GPIO_CTRL_GP24_SF_BYTE_ADDR ) +#define GPIO_CTRL_GP26_PCM_BYTE_VAL REG8_VAL(GPIO_CTRL_GP26_PCM_BYTE_ADDR ) +#define GPIO_CTRL_GP60_USB_BYTE_VAL REG8_VAL(GPIO_CTRL_GP60_USB_BYTE_ADDR ) +#define GPIO_CTRL_GP62_WAKEUP_SUS_BYTE_VAL REG8_VAL(GPIO_CTRL_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_CTRL_GP63_SD02CD_BYTE_VAL REG8_VAL(GPIO_CTRL_GP63_SD02CD_BYTE_ADDR ) +#define GPIO_OC_GP0_BYTE_VAL REG8_VAL(GPIO_OC_GP0_BYTE_ADDR ) +#define GPIO_OC_GP1_BYTE_VAL REG8_VAL(GPIO_OC_GP1_BYTE_ADDR ) +#define GPIO_OC_GP2_BYTE_VAL REG8_VAL(GPIO_OC_GP2_BYTE_ADDR ) +#define GPIO_OC_GP4_VDOUT_7_0_BYTE_VAL REG8_VAL(GPIO_OC_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_OC_GP5_VDOUT_15_8_BYTE_VAL REG8_VAL(GPIO_OC_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_OC_GP6_VDOUT_23_16_BYTE_VAL REG8_VAL(GPIO_OC_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_OC_GP7_VD_BYTE_VAL REG8_VAL(GPIO_OC_GP7_VD_BYTE_ADDR ) +#define GPIO_OC_GP8_VDIN_BYTE_VAL REG8_VAL(GPIO_OC_GP8_VDIN_BYTE_ADDR ) +#define GPIO_OC_GP9_VSYNC_BYTE_VAL REG8_VAL(GPIO_OC_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_OC_GP10_I2S_BYTE_VAL REG8_VAL(GPIO_OC_GP10_I2S_BYTE_ADDR ) +#define GPIO_OC_GP11_I2S_BYTE_VAL REG8_VAL(GPIO_OC_GP11_I2S_BYTE_ADDR ) +#define GPIO_OC_GP12_SPI_BYTE_VAL REG8_VAL(GPIO_OC_GP12_SPI_BYTE_ADDR ) +#define GPIO_OC_GP13_SD0_BYTE_VAL REG8_VAL(GPIO_OC_GP13_SD0_BYTE_ADDR ) +#define GPIO_OC_GP14_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_OC_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_OC_GP15_NAND_BYTE_VAL REG8_VAL(GPIO_OC_GP15_NAND_BYTE_ADDR ) +#define GPIO_OC_GP16_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_OC_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_OC_GP17_I2C_BYTE_VAL REG8_VAL(GPIO_OC_GP17_I2C_BYTE_ADDR ) +#define GPIO_OC_GP18_UART_BYTE_VAL REG8_VAL(GPIO_OC_GP18_UART_BYTE_ADDR ) +#define GPIO_OC_GP19_SD2_BYTE_VAL REG8_VAL(GPIO_OC_GP19_SD2_BYTE_ADDR ) +#define GPIO_OC_GP20_PWM0_BYTE_VAL REG8_VAL(GPIO_OC_GP20_PWM0_BYTE_ADDR ) +#define GPIO_OC_GP21_HDMI_BYTE_VAL REG8_VAL(GPIO_OC_GP21_HDMI_BYTE_ADDR ) +#define GPIO_OC_GP22_I2C3_BYTE_VAL REG8_VAL(GPIO_OC_GP22_I2C3_BYTE_ADDR ) +#define GPIO_OC_GP24_SF_BYTE_VAL REG8_VAL(GPIO_OC_GP24_SF_BYTE_ADDR ) +#define GPIO_OC_GP26_PCM_BYTE_VAL REG8_VAL(GPIO_OC_GP26_PCM_BYTE_ADDR ) +#define GPIO_OC_GP60_USB_BYTE_VAL REG8_VAL(GPIO_OC_GP60_USB_BYTE_ADDR ) +#define GPIO_OC_GP62_WAKEUP_SUS_BYTE_VAL REG8_VAL(GPIO_OC_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_OC_GP63_SD02CD_BYTE_VAL REG8_VAL(GPIO_OC_GP63_SD02CD_BYTE_ADDR ) +#define GPIO_OD_GP0_BYTE_VAL REG8_VAL(GPIO_OD_GP0_BYTE_ADDR ) +#define GPIO_OD_GP1_BYTE_VAL REG8_VAL(GPIO_OD_GP1_BYTE_ADDR ) +#define GPIO_OD_GP2_BYTE_VAL REG8_VAL(GPIO_OD_GP2_BYTE_ADDR ) +#define GPIO_OD_GP4_VDOUT_7_0_BYTE_VAL REG8_VAL(GPIO_OD_GP4_VDOUT_7_0_BYTE_ADDR ) +#define GPIO_OD_GP5_VDOUT_15_8_BYTE_VAL REG8_VAL(GPIO_OD_GP5_VDOUT_15_8_BYTE_ADDR ) +#define GPIO_OD_GP6_VDOUT_23_16_BYTE_VAL REG8_VAL(GPIO_OD_GP6_VDOUT_23_16_BYTE_ADDR ) +#define GPIO_OD_GP7_VD_BYTE_VAL REG8_VAL(GPIO_OD_GP7_VD_BYTE_ADDR ) +#define GPIO_OD_GP8_VDIN_BYTE_VAL REG8_VAL(GPIO_OD_GP8_VDIN_BYTE_ADDR ) +#define GPIO_OD_GP9_VSYNC_BYTE_VAL REG8_VAL(GPIO_OD_GP9_VSYNC_BYTE_ADDR ) +#define GPIO_OD_GP10_I2S_BYTE_VAL REG8_VAL(GPIO_OD_GP10_I2S_BYTE_ADDR ) +#define GPIO_OD_GP11_I2S_BYTE_VAL REG8_VAL(GPIO_OD_GP11_I2S_BYTE_ADDR ) +#define GPIO_OD_GP12_SPI_BYTE_VAL REG8_VAL(GPIO_OD_GP12_SPI_BYTE_ADDR ) +#define GPIO_OD_GP13_SD0_BYTE_VAL REG8_VAL(GPIO_OD_GP13_SD0_BYTE_ADDR ) +#define GPIO_OD_GP14_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_OD_GP14_NAND_SD1_BYTE_ADDR ) +#define GPIO_OD_GP15_NAND_BYTE_VAL REG8_VAL(GPIO_OD_GP15_NAND_BYTE_ADDR ) +#define GPIO_OD_GP16_NAND_SD1_BYTE_VAL REG8_VAL(GPIO_OD_GP16_NAND_SD1_BYTE_ADDR ) +#define GPIO_OD_GP17_I2C_BYTE_VAL REG8_VAL(GPIO_OD_GP17_I2C_BYTE_ADDR ) +#define GPIO_OD_GP18_UART_BYTE_VAL REG8_VAL(GPIO_OD_GP18_UART_BYTE_ADDR ) +#define GPIO_OD_GP19_SD2_BYTE_VAL REG8_VAL(GPIO_OD_GP19_SD2_BYTE_ADDR ) +#define GPIO_OD_GP20_PWM0_BYTE_VAL REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR ) +#define GPIO_OD_GP21_HDMI_BYTE_VAL REG8_VAL(GPIO_OD_GP21_HDMI_BYTE_ADDR ) +#define GPIO_OD_GP23_I2C3_BYTE_VAL REG8_VAL(GPIO_OD_GP23_I2C3_BYTE_ADDR ) +#define GPIO_OD_GP24_SF_BYTE_VAL REG8_VAL(GPIO_OD_GP24_SF_BYTE_ADDR ) +#define GPIO_OD_GP26_PCM_BYTE_VAL REG8_VAL(GPIO_OD_GP26_PCM_BYTE_ADDR ) +#define GPIO_OD_GP60_USB_BYTE_VAL REG8_VAL(GPIO_OD_GP60_USB_BYTE_ADDR ) +#define GPIO_OD_GP62_WAKEUP_SUS_BYTE_VAL REG8_VAL(GPIO_OD_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define GPIO_OD_GP63_SD02CD_BYTE_VAL REG8_VAL(GPIO_OD_GP63_SD02CD_BYTE_ADDR ) +#define STRAP_STATUS_VAL REG32_VAL(STRAP_STATUS_ADDR ) +#define AHB_CTRL_4BYTE_VAL REG32_VAL(AHB_CTRL_4BYTE_ADDR ) +#define USB_OP_CTRL_4BYTE_VAL REG32_VAL(USB_OP_CTRL_4BYTE_ADDR ) +#define BONDING_OPTION_4BYTE_VAL REG32_VAL(BONDING_OPTION_4BYTE_ADDR ) +#define PIN_SHARING_SEL_4BYTE_VAL REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR ) +#define TPIU_CLK_DATA_4BYTE_VAL REG32_VAL(TPIU_CLK_DATA_4BYTE_ADDR ) +#define GPIO0_INT_REQ_TYPE_VAL REG8_VAL(GPIO0_INT_REQ_TYPE_ADDR ) +#define GPIO1_INT_REQ_TYPE_VAL REG8_VAL(GPIO1_INT_REQ_TYPE_ADDR ) +#define GPIO2_INT_REQ_TYPE_VAL REG8_VAL(GPIO2_INT_REQ_TYPE_ADDR ) +#define GPIO3_INT_REQ_TYPE_VAL REG8_VAL(GPIO3_INT_REQ_TYPE_ADDR ) +#define GPIO4_INT_REQ_TYPE_VAL REG8_VAL(GPIO4_INT_REQ_TYPE_ADDR ) +#define GPIO5_INT_REQ_TYPE_VAL REG8_VAL(GPIO5_INT_REQ_TYPE_ADDR ) +#define GPIO6_INT_REQ_TYPE_VAL REG8_VAL(GPIO6_INT_REQ_TYPE_ADDR ) +#define GPIO7_INT_REQ_TYPE_VAL REG8_VAL(GPIO7_INT_REQ_TYPE_ADDR ) +#define GPIO8_INT_REQ_TYPE_VAL REG8_VAL(GPIO8_INT_REQ_TYPE_ADDR ) +#define GPIO9_INT_REQ_TYPE_VAL REG8_VAL(GPIO9_INT_REQ_TYPE_ADDR ) +#define GPIO10_INT_REQ_TYPE_VAL REG8_VAL(GPIO10_INT_REQ_TYPE_ADDR ) +#define GPIO11_INT_REQ_TYPE_VAL REG8_VAL(GPIO11_INT_REQ_TYPE_ADDR ) +#define GPIO12_INT_REQ_TYPE_VAL REG8_VAL(GPIO12_INT_REQ_TYPE_ADDR ) +#define GPIO13_INT_REQ_TYPE_VAL REG8_VAL(GPIO13_INT_REQ_TYPE_ADDR ) +#define GPIO18_INT_REQ_TYPE_VAL REG8_VAL(GPIO18_INT_REQ_TYPE_ADDR ) +#define GPIO19_INT_REQ_TYPE_VAL REG8_VAL(GPIO19_INT_REQ_TYPE_ADDR ) +#define VOUT20_INT_REQ_TYPE_VAL REG8_VAL(VOUT20_INT_REQ_TYPE_ADDR ) +#define VOUT21_INT_REQ_TYPE_VAL REG8_VAL(VOUT21_INT_REQ_TYPE_ADDR ) +#define VOUT22_INT_REQ_TYPE_VAL REG8_VAL(VOUT22_INT_REQ_TYPE_ADDR ) +#define VOUT23_INT_REQ_TYPE_VAL REG8_VAL(VOUT23_INT_REQ_TYPE_ADDR ) +#define GPIO20_INT_REQ_TYPE_VAL REG8_VAL(GPIO20_INT_REQ_TYPE_ADDR ) +#define GPIO21_INT_REQ_TYPE_VAL REG8_VAL(GPIO21_INT_REQ_TYPE_ADDR ) +#define GPIO22_INT_REQ_TYPE_VAL REG8_VAL(GPIO22_INT_REQ_TYPE_ADDR ) +#define GPIO23_INT_REQ_TYPE_VAL REG8_VAL(GPIO23_INT_REQ_TYPE_ADDR ) +#define GPIO24_INT_REQ_TYPE_VAL REG8_VAL(GPIO24_INT_REQ_TYPE_ADDR ) +#define GPIO25_INT_REQ_TYPE_VAL REG8_VAL(GPIO25_INT_REQ_TYPE_ADDR ) +#define GPIO0_INT_REQ_STS_VAL REG8_VAL(GPIO0_INT_REQ_STS_ADDR ) +#define GPIO1_INT_REQ_STS_VAL REG8_VAL(GPIO1_INT_REQ_STS_ADDR ) +#define GPIO2_INT_REQ_STS_VAL REG8_VAL(GPIO2_INT_REQ_STS_ADDR ) +#define GPIO3_INT_REQ_STS_VAL REG8_VAL(GPIO3_INT_REQ_STS_ADDR ) +#define DRV_DVO_CLK_BYTE_VAL REG8_VAL(DRV_DVO_CLK_BYTE_ADDR ) +#define DRV_DVO_VDEN_BYTE_VAL REG8_VAL(DRV_DVO_VDEN_BYTE_ADDR ) +#define SD0_DPCTL_4BYTE_VAL REG32_VAL(SD0_DPCTL_4BYTE_ADDR ) +#define SD0_DNCTL_4BYTE_VAL REG32_VAL(SD0_DNCTL_4BYTE_ADDR ) +#define DRV_SD0_USB_BYTE_VAL REG8_VAL(DRV_SD0_USB_BYTE_ADDR ) +#define DRV_USB_SWOC0_BYTE_VAL REG8_VAL(DRV_USB_SWOC0_BYTE_ADDR ) +#define DRV_USB_OC12_BYTE_VAL REG8_VAL(DRV_USB_OC12_BYTE_ADDR ) +#define DRV_USBOC3_CIR_BYTE_VAL REG8_VAL(DRV_USBOC3_CIR_BYTE_ADDR ) +#define DRV_PWREN_BYTE_VAL REG8_VAL(DRV_PWREN_BYTE_ADDR ) +#define DRV_PWREN_WAKEUP0_BYTE_VAL REG8_VAL(DRV_PWREN_WAKEUP0_BYTE_ADDR ) +#define DRV_SUSGP01_BYTE_VAL REG8_VAL(DRV_SUSGP01_BYTE_ADDR ) +#define DRV_WAKEUP23_BYTE_VAL REG8_VAL(DRV_WAKEUP23_BYTE_ADDR ) +#define DRV_WAKEUP45_BYTE_VAL REG8_VAL(DRV_WAKEUP45_BYTE_ADDR ) +#define DRV_I2C_BYTE_VAL REG8_VAL(DRV_I2C_BYTE_ADDR ) +#define DRV_HDMI_BYTE_VAL REG8_VAL(DRV_HDMI_BYTE_ADDR ) +#define PULL_EN_GP0_BYTE_VAL REG8_VAL(PULL_EN_GP0_BYTE_ADDR ) +#define PULL_EN_GP1_BYTE_VAL REG8_VAL(PULL_EN_GP1_BYTE_ADDR ) +#define PULL_EN_GP2_BYTE_VAL REG8_VAL(PULL_EN_GP2_BYTE_ADDR ) +#define PULL_EN_GP4_VDOUT_7_0_BYTE_VAL REG8_VAL(PULL_EN_GP4_VDOUT_7_0_BYTE_ADDR ) +#define PULL_EN_GP5_VDOUT_15_8_BYTE_VAL REG8_VAL(PULL_EN_GP5_VDOUT_15_8_BYTE_ADDR ) +#define PULL_EN_GP6_VDOUT_23_16_BYTE_VAL REG8_VAL(PULL_EN_GP6_VDOUT_23_16_BYTE_ADDR ) +#define PULL_EN_GP7_VD_BYTE_VAL REG8_VAL(PULL_EN_GP7_VD_BYTE_ADDR ) +#define PULL_EN_GP8_VDIN_BYTE_VAL REG8_VAL(PULL_EN_GP8_VDIN_BYTE_ADDR ) +#define PULL_EN_GP9_VSYNC_BYTE_VAL REG8_VAL(PULL_EN_GP9_VSYNC_BYTE_ADDR ) +#define PULL_EN_GP10_I2S_BYTE_VAL REG8_VAL(PULL_EN_GP10_I2S_BYTE_ADDR ) +#define PULL_EN_GP11_I2S_BYTE_VAL REG8_VAL(PULL_EN_GP11_I2S_BYTE_ADDR ) +#define PULL_EN_GP12_SPI_BYTE_VAL REG8_VAL(PULL_EN_GP12_SPI_BYTE_ADDR ) +#define PULL_EN_GP13_SD0_BYTE_VAL REG8_VAL(PULL_EN_GP13_SD0_BYTE_ADDR ) +#define PULL_EN_GP14_NAND_BYTE_VAL REG8_VAL(PULL_EN_GP14_NAND_BYTE_ADDR ) +#define PULL_EN_GP15_NAND_BYTE_VAL REG8_VAL(PULL_EN_GP15_NAND_BYTE_ADDR ) +#define PULL_EN_GP16_NANDIO_BYTE_VAL REG8_VAL(PULL_EN_GP16_NANDIO_BYTE_ADDR ) +#define PULL_EN_GP17_I2C_BYTE_VAL REG8_VAL(PULL_EN_GP17_I2C_BYTE_ADDR ) +#define PULL_EN_GP18_UART_BYTE_VAL REG8_VAL(PULL_EN_GP18_UART_BYTE_ADDR ) +#define PULL_EN_GP19_SD2_BYTE_VAL REG8_VAL(PULL_EN_GP19_SD2_BYTE_ADDR ) +#define PULL_EN_GP20_PWM0_BYTE_VAL REG8_VAL(PULL_EN_GP20_PWM0_BYTE_ADDR ) +#define PULL_EN_GP21_HDMI_BYTE_VAL REG8_VAL(PULL_EN_GP21_HDMI_BYTE_ADDR ) +#define PULL_EN_GP23_I2C3_BYTE_VAL REG8_VAL(PULL_EN_GP23_I2C3_BYTE_ADDR ) +#define PULL_EN_GP24_SF_BYTE_VAL REG8_VAL(PULL_EN_GP24_SF_BYTE_ADDR ) +#define PULL_EN_GP26_PCM_BYTE_VAL REG8_VAL(PULL_EN_GP26_PCM_BYTE_ADDR ) +#define PULL_EN_GP60_USB_BYTE_VAL REG8_VAL(PULL_EN_GP60_USB_BYTE_ADDR ) +#define PULL_EN_GP62_WAKEUP_SUS_BYTE_VAL REG8_VAL(PULL_EN_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define PULL_EN_GP63_SD02_BYTE_VAL REG8_VAL(PULL_EN_GP63_SD02_BYTE_ADDR ) +#define PULL_CTRL_GP0_BYTE_VAL REG8_VAL(PULL_CTRL_GP0_BYTE_ADDR ) +#define PULL_CTRL_GP1_BYTE_VAL REG8_VAL(PULL_CTRL_GP1_BYTE_ADDR ) +#define PULL_CTRL_GP2_BYTE_VAL REG8_VAL(PULL_CTRL_GP2_BYTE_ADDR ) +#define PULL_CTRL_GP4_VDOUT_7_0_BYTE_VAL REG8_VAL(PULL_CTRL_GP4_VDOUT_7_0_BYTE_ADDR ) +#define PULL_CTRL_GP5_VDOUT_15_8_BYTE_VAL REG8_VAL(PULL_CTRL_GP5_VDOUT_15_8_BYTE_ADDR ) +#define PULL_CTRL_GP6_VDOUT_23_16_BYTE_VAL REG8_VAL(PULL_CTRL_GP6_VDOUT_23_16_BYTE_ADDR ) +#define PULL_CTRL_GP7_VD_BYTE_VAL REG8_VAL(PULL_CTRL_GP7_VD_BYTE_ADDR ) +#define PULL_CTRL_GP8_VDIN_BYTE_VAL REG8_VAL(PULL_CTRL_GP8_VDIN_BYTE_ADDR ) +#define PULL_CTRL_GP9_VSYNC_BYTE_VAL REG8_VAL(PULL_CTRL_GP9_VSYNC_BYTE_ADDR ) +#define PULL_CTRL_GP10_I2S_BYTE_VAL REG8_VAL(PULL_CTRL_GP10_I2S_BYTE_ADDR ) +#define PULL_CTRL_GP11_I2S_BYTE_VAL REG8_VAL(PULL_CTRL_GP11_I2S_BYTE_ADDR ) +#define PULL_CTRL_GP12_SPI_BYTE_VAL REG8_VAL(PULL_CTRL_GP12_SPI_BYTE_ADDR ) +#define PULL_CTRL_GP13_SD0_BYTE_VAL REG8_VAL(PULL_CTRL_GP13_SD0_BYTE_ADDR ) +#define PULL_CTRL_GP14_NAND_BYTE_VAL REG8_VAL(PULL_CTRL_GP14_NAND_BYTE_ADDR ) +#define PULL_CTRL_GP15_NAND_BYTE_VAL REG8_VAL(PULL_CTRL_GP15_NAND_BYTE_ADDR ) +#define PULL_CTRL_GP16_NANDIO_BYTE_VAL REG8_VAL(PULL_CTRL_GP16_NANDIO_BYTE_ADDR ) +#define PULL_CTRL_GP17_I2C_BYTE_VAL REG8_VAL(PULL_CTRL_GP17_I2C_BYTE_ADDR ) +#define PULL_CTRL_GP18_UART_BYTE_VAL REG8_VAL(PULL_CTRL_GP18_UART_BYTE_ADDR ) +#define PULL_CTRL_GP19_SD2_BYTE_VAL REG8_VAL(PULL_CTRL_GP19_SD2_BYTE_ADDR ) +#define PULL_CTRL_GP20_PWM0_BYTE_VAL REG8_VAL(PULL_CTRL_GP20_PWM0_BYTE_ADDR ) +#define PULL_CTRL_GP21_HDMI_BYTE_VAL REG8_VAL(PULL_CTRL_GP21_HDMI_BYTE_ADDR ) +#define PULL_CTRL_GP23_I2C3_BYTE_VAL REG8_VAL(PULL_CTRL_GP23_I2C3_BYTE_ADDR ) +#define PULL_CTRL_GP24_SF_BYTE_VAL REG8_VAL(PULL_CTRL_GP24_SF_BYTE_ADDR ) +#define PULL_CTRL_GP26_PCM_BYTE_VAL REG8_VAL(PULL_CTRL_GP26_PCM_BYTE_ADDR ) +#define PULL_CTRL_GP27_SD0_BYTE_VAL REG8_VAL(PULL_CTRL_GP27_SD0_BYTE_ADDR ) +#define PULL_CTRL_GP60_USB_BYTE_VAL REG8_VAL(PULL_CTRL_GP60_USB_BYTE_ADDR ) +#define PULL_CTRL_GP62_WAKEUP_SUS_BYTE_VAL REG8_VAL(PULL_CTRL_GP62_WAKEUP_SUS_BYTE_ADDR ) +#define PULL_CTRL_GP63_SD02_BYTE_VAL REG8_VAL(PULL_CTRL_GP63_SD02_BYTE_ADDR ) +#define DRV_GPIO_7_0_4BYTE_VAL REG32_VAL(DRV_GPIO_7_0_4BYTE_ADDR ) +#define DRV_GPIO_13_8_4BYTE_VAL REG32_VAL(DRV_GPIO_13_8_4BYTE_ADDR ) +#define DRV_GPIO_19_14_4BYTE_VAL REG32_VAL(DRV_GPIO_19_14_4BYTE_ADDR ) +#define DRV_VDIN_3_0_4BYTE_VAL REG32_VAL(DRV_VDIN_3_0_4BYTE_ADDR ) +#define DRV_VDIN_4_6_4BYTE_VAL REG32_VAL(DRV_VDIN_3_0_4BYTE_ADDR ) +#define DRV_VDIN_SPI_4BYTE_VAL REG32_VAL(DRV_VDIN_SPI_4BYTE_ADDR ) +#define DRV_SPI_NAND_4BYTE_VAL REG32_VAL(DRV_SPI_NAND_4BYTE_ADDR ) +#define DRV_NAND_4BYTE_VAL REG32_VAL(DRV_NAND_4BYTE_ADDR ) +#define DRV_NANDIO_4BYTE_VAL REG32_VAL(DRV_NANDIO_4BYTE_ADDR ) +#define DRV_HDMI_I2C_4BYTE_VAL REG32_VAL(DRV_HDMI_I2C_4BYTE_ADDR ) +#define DRV_I2C_SD0_4BYTE_VAL REG32_VAL(DRV_I2C_SD0_4BYTE_ADDR ) +#define DRV_SD0_SD2_4BYTE_VAL REG32_VAL(DRV_SD0_SD2_4BYTE_ADDR ) +#define DRV_SD2_I2S_4BYTE_VAL REG32_VAL(DRV_SD2_I2S_4BYTE_ADDR ) +#define DRV_I2S_UART_4BYTE_VAL REG32_VAL(DRV_I2S_UART_4BYTE_ADDR ) +#define DRV_UART_4BYTE_VAL REG32_VAL(DRV_UART_4BYTE_ADDR ) +#define DRV_SF_JTAGT_4BYTE_VAL REG32_VAL(DRV_SF_JTAGT_4BYTE_ADDR ) +#define DRV_JTAGT_PWM_4BYTE_VAL REG32_VAL(DRV_JTAGT_PWM_4BYTE_ADDR ) +#define DRV_PCM_BYTE_VAL REG8_VAL(DRV_PCM_BYTE_ADDR ) +#define DRV_SPI_BYTE_VAL REG8_VAL(DRV_SPI_BYTE_ADDR ) + +#define GPIO_STRAP_STS_VAL REG32_VAL(0x0100+BA_GPIO) + +/* [Rx300] GPIO Interrupt Request Type Register */ +#define GPIO_IRQT_LOW 0 +#define GPIO_IRQT_HIGH BIT0 +#define GPIO_IRQT_FALLING BIT1 +#define GPIO_IRQT_RISING (BIT1 | BIT0) +#define GPIO_IRQT_DOUBLE BIT2 + +/* GPIO Control Register for I2C */ +#define GPIO_I2C0_SCL BIT0 +#define GPIO_I2C0_SDA BIT1 +#define GPIO_I2C1_SCL BIT2 +#define GPIO_I2C1_SDA BIT3 +#define GPIO_I2C2_SCL BIT4 +#define GPIO_I2C2_SDA BIT5 +#define GPIO_I2C3_SCL BIT0 +#define GPIO_I2C3_SDA BIT1 +#define GPIO_I2C0_SCL_PULL_EN BIT0 +#define GPIO_I2C0_SDA_PULL_EN BIT1 +#define GPIO_I2C1_SCL_PULL_EN BIT2 +#define GPIO_I2C1_SDA_PULL_EN BIT3 +#define GPIO_I2C2_SCL_PULL_EN BIT4 +#define GPIO_I2C2_SDA_PULL_EN BIT5 +#define GPIO_I2C3_SCL_PULL_EN BIT0 +#define GPIO_I2C3_SDA_PULL_EN BIT1 + +#endif +/*=== END wmt_gpio.h ==========================================================*/ + diff --git a/common/wmt_display/hw/wmt_i2c.h b/common/wmt_display/hw/wmt_i2c.h new file mode 100755 index 0000000..9c5033e --- /dev/null +++ b/common/wmt_display/hw/wmt_i2c.h @@ -0,0 +1,316 @@ +/*++ + linux/include/asm-arm/arch-wmt/wmt_i2c.h + + Copyright (c) 2008 WonderMedia Technologies, Inc. + + This program is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software Foundation, + either version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + PARTICULAR PURPOSE. See the GNU General Public License for more details. + You should have received a copy of the GNU General Public License along with + this program. If not, see <http://www.gnu.org/licenses/>. + + WonderMedia Technologies, Inc. + 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. + +--*/ +/* Be sure that virtual mapping is defined right */ + + +#ifndef _WMT_I2C_H_ +#define _WMT_I2C_H_ +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ + +#include "wmt_mmap.h" +/* + * Refer I2C 0.1 Module + * + */ +/* + i2c api address + + Since i2c bus would probe all device which connect with it to add i2c adapter + ,but we dont make sure which would connect with it. In order to reduce probe time + ,we give a fake slave address for probing only. + Be carefully, the i2c api address must be different from real device address +*/ + +#define WMT_I2C_API_I2C_ADDR 0x59 /*API address*/ + +/* + * Address + */ +#define I2C_CR_ADDR (0x0000+I2C_BASE_ADDR) +#define I2C_TCR_ADDR (0x0002+I2C_BASE_ADDR) +#define I2C_CSR_ADDR (0x0004+I2C_BASE_ADDR) +#define I2C_ISR_ADDR (0x0006+I2C_BASE_ADDR) +#define I2C_IMR_ADDR (0x0008+I2C_BASE_ADDR) +#define I2C_CDR_ADDR (0x000A+I2C_BASE_ADDR) +#define I2C_TR_ADDR (0x000C+I2C_BASE_ADDR) +#define I2C_DIV_ADDR (0x000E+I2C_BASE_ADDR) + +#define I2C1_CR_ADDR (0x0000+I2C1_BASE_ADDR) +#define I2C1_TCR_ADDR (0x0002+I2C1_BASE_ADDR) +#define I2C1_CSR_ADDR (0x0004+I2C1_BASE_ADDR) +#define I2C1_ISR_ADDR (0x0006+I2C1_BASE_ADDR) +#define I2C1_IMR_ADDR (0x0008+I2C1_BASE_ADDR) +#define I2C1_CDR_ADDR (0x000A+I2C1_BASE_ADDR) +#define I2C1_TR_ADDR (0x000C+I2C1_BASE_ADDR) +#define I2C1_DIV_ADDR (0x000E+I2C1_BASE_ADDR) +/* Slave Address*/ +#define I2C_SCR_ADDR (0x0010+I2C_BASE_ADDR) +#define I2C_SSR_ADDR (0x0012+I2C_BASE_ADDR) +#define I2C_SISR_ADDR (0x0014+I2C_BASE_ADDR) +#define I2C_SIMR_ADDR (0x0016+I2C_BASE_ADDR) +#define I2C_SDR_ADDR (0x0018+I2C_BASE_ADDR) +#define I2C_STR_ADDR (0x001A+I2C_BASE_ADDR) + +/* + * Registers + */ +#define I2C_CR_REG REG16_PTR(0x0000+I2C_BASE_ADDR) +#define I2C_TCR_REG REG16_PTR(0x0002+I2C_BASE_ADDR) +#define I2C_CSR_REG REG16_PTR(0x0004+I2C_BASE_ADDR) +#define I2C_ISR_REG REG16_PTR(0x0006+I2C_BASE_ADDR) +#define I2C_IMR_REG REG16_PTR(0x0008+I2C_BASE_ADDR) +#define I2C_CDR_REG REG16_PTR(0x000A+I2C_BASE_ADDR) +#define I2C_TR_REG REG16_PTR(0x000C+I2C_BASE_ADDR) +#define I2C_DIV_REG REG16_PTR(0x000E+I2C_BASE_ADDR) + +#define I2C1_CR_REG REG16_PTR(0x0000+I2C1_BASE_ADDR) +#define I2C1_TCR_REG REG16_PTR(0x0002+I2C1_BASE_ADDR) +#define I2C1_CSR_REG REG16_PTR(0x0004+I2C1_BASE_ADDR) +#define I2C1_ISR_REG REG16_PTR(0x0006+I2C1_BASE_ADDR) +#define I2C1_IMR_REG REG16_PTR(0x0008+I2C1_BASE_ADDR) +#define I2C1_CDR_REG REG16_PTR(0x000A+I2C1_BASE_ADDR) +#define I2C1_TR_REG REG16_PTR(0x000C+I2C1_BASE_ADDR) +#define I2C1_DIV_REG REG16_PTR(0x000E+I2C1_BASE_ADDR) +/* Slave Registers*/ +#define I2C_SCR_REG REG16_PTR(0x0010+I2C_BASE_ADDR) +#define I2C_SSR_REG REG16_PTR(0x0012+I2C_BASE_ADDR) +#define I2C_SISR_REG REG16_PTR(0x0014+I2C_BASE_ADDR) +#define I2C_SIMR_REG REG16_PTR(0x0016+I2C_BASE_ADDR) +#define I2C_SDR_REG REG16_PTR(0x0018+I2C_BASE_ADDR) +#define I2C_STR_REG REG16_PTR(0x001A+I2C_BASE_ADDR) + +/* + * Val Registers + */ +#define I2C_CR_VAL REG16_VAL(0x0000+I2C_BASE_ADDR) +#define I2C_TCR_VAL REG16_VAL(0x0002+I2C_BASE_ADDR) +#define I2C_CSR_VAL REG16_VAL(0x0004+I2C_BASE_ADDR) +#define I2C_ISR_VAL REG16_VAL(0x0006+I2C_BASE_ADDR) +#define I2C_IMR_VAL REG16_VAL(0x0008+I2C_BASE_ADDR) +#define I2C_CDR_VAL REG16_VAL(0x000A+I2C_BASE_ADDR) +#define I2C_TR_VAL REG16_VAL(0x000C+I2C_BASE_ADDR) +#define I2C_DIV_VAL REG16_VAL(0x000E+I2C_BASE_ADDR) + +#define I2C1_CR_VAL REG16_VAL(0x0000+I2C1_BASE_ADDR) +#define I2C1_TCR_VAL REG16_VAL(0x0002+I2C1_BASE_ADDR) +#define I2C1_CSR_VAL REG16_VAL(0x0004+I2C1_BASE_ADDR) +#define I2C1_ISR_VAL REG16_VAL(0x0006+I2C1_BASE_ADDR) +#define I2C1_IMR_VAL REG16_VAL(0x0008+I2C1_BASE_ADDR) +#define I2C1_CDR_VAL REG16_VAL(0x000A+I2C1_BASE_ADDR) +#define I2C1_TR_VAL REG16_VAL(0x000C+I2C1_BASE_ADDR) +#define I2C1_DIV_VAL REG16_VAL(0x000E+I2C1_BASE_ADDR) +/* Slave Val Registers*/ +#define I2C_SCR_VAL REG16_VAL(0x0010+I2C_BASE_ADDR) +#define I2C_SSR_VAL REG16_VAL(0x0012+I2C_BASE_ADDR) +#define I2C_SISR_VAL REG16_VAL(0x0014+I2C_BASE_ADDR) +#define I2C_SIMR_VAL REG16_VAL(0x0016+I2C_BASE_ADDR) +#define I2C_SDR_VAL REG16_VAL(0x0018+I2C_BASE_ADDR) +#define I2C_STR_VAL REG16_VAL(0x001A+I2C_BASE_ADDR) + +/* + * I2C_CR_REG + * I2C Controller Control + */ +/* Reserved [15:05] */ +/* [04:04] -- PCLK_SLE tied to Zero */ +#define I2C_CR_CPU_RDY 0x0008 +#define I2C_CR_TX_END 0x0004 +#define I2C_CR_TX_NEXT_NO_ACK 0x0002 +#define I2C_CR_TX_NEXT_ACK 0x0000 +#define I2C_CR_ENABLE 0x0001 +#define I2C_SLAV_MODE_SEL 0x8000 +/* + * I2C_TCR_REG + * I2C Transfer Control + * + */ +#define I2C_TCR_HS_MODE 0x2000 /* [13:13] */ +#define I2C_TCR_STANDARD_MODE 0x0000 /* [15:15] */ +#define I2C_TCR_FAST_MODE 0x8000 +#define I2C_TCR_MASTER_WRITE 0x0000 /* [14:14] */ +#define I2C_TCR_MASTER_READ 0x4000 +/* Reserved [13:07] */ +#define I2C_TCR_SLAVE_ADDR_MASK 0x007F /* [06:00] */ + +/* + * I2C_CSR_REG + * I2C Status + * + */ +/* Reserved [15:02] */ +#define I2C_READY 0x0002 /* [01:01] R */ +#define I2C_BUSY 0x0000 +#define I2C_STATUS_MASK 0x0002 +#define I2C_CSR_RCV_ACK 0x0000 /* [00:00] R */ +#define I2C_CSR_RCV_NOT_ACK 0x0001 +#define I2C_CSR_RCV_ACK_MASK 0x0001 + +/* + * I2C_ISR_REG + * I2C Interrupt Status + * + */ +/* Reserved [15:03] */ +#define I2C_ISR_SCL_TIME_OUT 0x0004 /* [02:02] R */ +#define I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR 0x0004 +#define I2C_ISR_BYTE_END 0x0002 /* [01:01] R */ +#define I2C_ISR_BYTE_END_WRITE_CLEAR 0x0002 +#define I2C_ISR_NACK_ADDR 0x0001 /* [00:00] R */ +#define I2C_ISR_NACK_ADDR_WRITE_CLEAR 0x0001 + +#define I2C_ISR_ALL_WRITE_CLEAR 0x0007 +/* + * I2C_IMR_REG + * I2C Interrupt Mask + * + */ +/* Reserved [15:03] */ +#define I2C_IMR_SCL_TIME_OUT_MASK 0x0004 /* [02:02] */ +#define I2C_IMR_BYTE_END_MASK 0x0002 /* [01:01] */ +#define I2C_IMR_NACK_ADDR_MASK 0x0001 /* [00:00] */ + +#define I2C_IMR_ALL_ENABLE 0x0007 +/* + * I2C_CDR_REG + * I2C Data IO + * + */ +#define I2C_CDR_DATA_READ_MASK 0xFF00 /* [15:08] */ +#define I2C_CDR_DATA_WRITE_MASK 0x00FF /* [07:00] */ + + +/* + * I2C_TR_REG + * I2C Timer Parameters + * + */ +#define I2C_TR_SCL_TIME_OUT_MASK 0xFF00 /* [15:08] */ +#define I2C_TR_FSTP_MASK 0x00FF /* [07:00] */ + +#define I2C_TR_STD_VALUE 0xFF64 /* standard mode*/ +#define I2C_TR_FAST_VALUE 0xFF19 /* fast mode*/ + + +/* + * I2C_DIV_REG + * I2C DIV + * + */ +#define APB_96M_I2C_DIV 7 /*Dean revised 2007/9/11 */ +#define APB_166M_I2C_DIV 12 /*Dean revised 2008/5/9 */ + + + +/* + * I2C slave registers setting + * + */ +#define HS_MASTER_CODE 0x0800 + +#define I2C_SLAVE_ADDR 0x59 +#define I2C_SLAVE_MASK 0x007F +#define I2C_SLAVE_NACK BIT12 +#define I2C_SLAVE_HS_MODE BIT14 +#define I2C_SLAVE_EN BIT15 + +#define I2C_SISR_SCL_TIME_OUT 0x0004 /* [02:02] R */ +#define I2C_SISR_SCL_TIME_OUT_WRITE_CLEAR 0x0004 +#define I2C_SISR_BYTE_END 0x0002 /* [01:01] R */ +#define I2C_SISR_BYTE_END_WRITE_CLEAR 0x0002 +#define I2C_SISR_DAT_REQ 0x0001 /* [00:00] R */ +#define I2C_SISR_DAT_REQ_WRITE_CLEAR 0x0001 + +#define I2C_SISR_ALL_WRITE_CLEAR 0x0007 + +#define I2C_SIMR_SCL_TIME_OUT_MASK 0x0004 /* [02:02] */ +#define I2C_SIMR_BYTE_END_MASK 0x0002 /* [01:01] */ +#define I2C_SIMR_NACK_ADDR_MASK 0x0001 /* [00:00] */ + +#define I2C_SIMR_ALL_ENABLE 0x0007 + +#define I2C_SRCV_NACK BIT0 +#define I2C_SREAD BIT1 +#define I2C_SACT BIT2 + +#define I2C_SLAVE_WRITE_DATA_SHIFT 0 +#define I2C_SLAVE_READ_DATA_SHIFT 8 +#define I2C_SLAVE_READ_DATA_MASK 0xFF00 +#define I2C_SLAVE_WRITE_DATA_MASK 0x00FF + +enum i2c_mode_e { + I2C_STANDARD_MODE = 0 , + I2C_FAST_MODE = 1, + I2C_HS_MODE = 2, +}; + +struct i2c_regs_s { + volatile unsigned short cr_reg; /* IIC controller control register*/ + volatile unsigned short tcr_reg; /* IIC controller transfer control register*/ + volatile unsigned short csr_reg; /* IIC controller status register*/ + volatile unsigned short isr_reg; /* IIC controller interrupt status register*/ + volatile unsigned short imr_reg; /* IIC controller interrupt mask register*/ + volatile unsigned short cdr_reg; /* IIC controller data I/O buffer register*/ + volatile unsigned short tr_reg; /* IIC controller time parameter register*/ + volatile unsigned short div_reg; /* IIC controller clock divider register*/ + volatile unsigned short scr_reg; /* IIC slave controller control register*/ + volatile unsigned short cssr_reg; /* IIC slave controller status register*/ + volatile unsigned short sisr_reg; /* IIC slave controller interrupt status register*/ + volatile unsigned short simr_reg; /* IIC slave controller interrupt mask register*/ + volatile unsigned short csdr_reg; /* IIC slave controller data I/O buffer register*/ + volatile unsigned short str_reg; /* IIC slave controller time parameter register*/ +}; + +#define SUSPEND_NOTIFY 0 +#define SUSPEND_SAVE_STATE 1 +#define SUSPEND_DISABLE 2 +#define SUSPEND_POWER_DOWN 3 +#define RESUME_POWER_ON 0 +#define RESUME_RESTORE_STATE 1 +#define RESUME_ENABLE 2 + +#define I2C_ALGO_WMT 0x00900000 /* via WMT on-chip i2c algo*/ + +#define I2C_ADAPTER_RETRIES 3 +#define I2C_ALGO_UDELAY 10 +#define I2C_ALGO_TIMEOUT 500 + +#define MAX_MESSAGES 65536 /* maximum number of messages to send*/ + + +#define I2C_SET_STANDARD_MODE 0x07A0 +#define I2C_SET_FAST_MODE 0x07A1 + +#if 0 +struct i2c_algo_wmt_data { + int (*write_msg)(unsigned int slave_addr, char *buf, unsigned int length , int restart, int last) ; + int (*read_msg)(unsigned int slave_addr, char *buf, unsigned int length , int restart, int last) ; + int (*send_request)(struct i2c_msg *msg, int msg_num, int non_block); +#ifdef CONFIG_SND_SOC_VT1603 + int (*vt1603_write_for_read)(unsigned int slave_addr, char *buf, unsigned int length , int restart, int last); +#endif + int (*wait_bus_not_busy) (void); + void (*reset) (void); + void (*set_mode)(enum i2c_mode_e) ; + int udelay; + int timeout; +}; +#endif + +#endif diff --git a/common/wmt_display/hw/wmt_mmap.h b/common/wmt_display/hw/wmt_mmap.h new file mode 100755 index 0000000..7e8214d --- /dev/null +++ b/common/wmt_display/hw/wmt_mmap.h @@ -0,0 +1,190 @@ +/*++ +linux/include/asm-arm/arch-wmt/wmt_mmap.h + +Copyright (c) 2008 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software Foundation, +either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + + +#ifndef __WMT_MMAP_H +#define __WMT_MMAP_H + +/** + * WMT Memory Map for Physical Address 0xD8000000 will be mapped to + * Virtual Address 0xFE000000 + */ +#define WMT_MMAP_OFFSET 0 + +#define EXTERNAL_AHB_BRIDGE_BASE_ADDR 0xB0000000 +#define INTERNAL_AHB_SLAVES_BASE_ADDR (0xD8000000 + WMT_MMAP_OFFSET) +#define INTERNAL_APB_SLAVES_BASE_ADDR (0xD8100000 + WMT_MMAP_OFFSET) + +/** + * Internal AHB Slaves Memory Address Map + */ +#define MEMORY_CTRL_V3_CFG_BASE_ADDR (0xD8000000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define MEMORY_CTRL_V4_CFG_BASE_ADDR (0xD8000400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define DMA_CTRL0_V3_CFG_BASE_ADDR (0xD8001000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define DMA_CTRL1_V3_CFG_BASE_ADDR (0xD8001400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define DMA_CTRL_V4_CFG_BASE_ADDR (0xD8001800 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define PICTOR_DMA_CTRL_CFG_BASE_ADDR (0xD8001C00 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define SF_MEM_CTRL_CFG_BASE_ADDR (0xD8002000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define LPC_MEM_CTRL_CFG_BASE_ADDR (0xD8003000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define SPI_MEM_CTRL_CFG_BASE_ADDR (0xD8003000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define ETHERNET_MAC_0_CFG_BASE_ADDR (0xD8004000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define ETHERNET_MAC_1_CFG_BASE_ADDR (0xD8005000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define SECURITY_ENGINE_CFG_BASE_ADDR (0xD8006000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define SECURITY_ENGINE_CFG_EXTENT_BASE_ADDR (0xD8006400 + WMT_MMAP_OFFSET) /* 3K , 8/16/32 RW */ +#define USB20_HOST_CFG_BASE_ADDR (0xD8007000 + WMT_MMAP_OFFSET) /* 2K , 8/16/32 RW */ +#define USB20_HOST_DEVICE_CFG_BASE_ADDR (0xD8007800 + WMT_MMAP_OFFSET) /* 2K , 8/16/32 RW */ +#define PATA_CTRL_CFG_BASE_ADDR (0xD8008000 + WMT_MMAP_OFFSET) /* 2K , 8/16/32 RW */ +#define PS2_CFG_BASE_ADDR (0xD8008800 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define USB20_HOST_CFG_EXTENT_BASE_ADDR (0xD8008C00 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define NF_CTRL_CFG_BASE_ADDR (0xD8009000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define NOR_CTRL_CFG_BASE_ADDR (0xD8009400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define USB20_DEVICE_CFG_BASE_ADDR (0xD8009800 + WMT_MMAP_OFFSET) /* 2K , 8/16/32 RW */ +#define SD0_SDIO_MMC_BASE_ADDR (0xD800A000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define SD1_SDIO_MMC_BASE_ADDR (0xD800A400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define MS_CTRL_CFG_BASE_ADDR (0xD800B000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define XD_CTRL_CFG_BASE_ADDR (0xD800B400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define CF_CTRL_CFG_BASE_ADDR (0xD800C000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define SATA_CTRL_CFG_BASE_ADDR (0xD800D000 + WMT_MMAP_OFFSET) /* 2K , 8/16/32 RW */ + +#define XOR_CTRL_CFG_BASE_ADDR (0xD800E000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define LCD_CTRL_CFG_BASE_ADDR (0xD800E400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define ASYNC_APB_BRIDGE_BASE_ADDR (0xD802FC00 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define LPC_TPM_CFG_BASE_ADDR (0xD8030000 + WMT_MMAP_OFFSET) /* 64K , 8/16/32 RW */ +#define LPC_SUPERIO_CFG_BASE_ADDR (0xD8040000 + WMT_MMAP_OFFSET) /* 64K , 8/16/32 RW */ + +#define VPU_BASE_ADDR (0xD8050100 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define VPU_BASE2_ADDR (0xD8050200 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define SPU1_BASE_ADDR (0xD8050100 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define SPU2_BASE_ADDR (0xD8050200 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GOVM_BASE_ADDR (0xD8050300 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GE1_BASE_ADDR (0xD8050400 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GE2_BASE_ADDR (0xD8050500 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GE3_BASE_ADDR (0xD8050600 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define DISP_BASE_ADDR (0xD8050700 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GOVRH_BASE1_ADDR (0xD8050800 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GOVRH_BASE2_ADDR (0xD8050900 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define VID_BASE_ADDR (0xD8050A00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define HDTV_CTRL_BASE_ADDR (0xD8050B00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GOVW_BASE_ADDR (0xD8050C00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define SCL_BASE_ADDR (0xD8050D00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define SCL_BASE2_ADDR (0xD8050000 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define DISP2_BASE_ADDR (0xD8050E00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define VPP_BASE_ADDR (0xD8050F00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define LVDS_BASE_ADDR (0xD8051000 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GOVRH2_BASE1_ADDR (0xD8051700 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define GOVRH2_BASE2_ADDR (0xD8051800 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ +#define HDMI_BASE2_ADDR (0xD8051F00 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ + +#define HDMI_TRANSMITTE_BASE_ADDR (0xD8060000 + WMT_MMAP_OFFSET) /* 64K , 8/16/32 RW */ +#define HDMI_CP_BASE_ADDR (0xD8070000 + WMT_MMAP_OFFSET) /* 64K , 8/16/32 RW */ + +#define USB2_OTG_CFG_BASE_ADDR (0xD80E4000 + WMT_MMAP_OFFSET) /* 16K , 8/16/32 RW */ + +#define AUDREGF_BASE_ADDR (0xD80ED800 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define PART_OF_AUDREGF_BASE_ADDR (0xD80EDC00 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define DSS_MBOX_BASE_ADDR (0xD80EE000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define DSS_PERM_BASE_ADDR (0xD80EE400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define VDU_BASE_ADDR (0xD80F0000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define SCRCNT_BASE_ADDR (0xD80F0400 + WMT_MMAP_OFFSET) /* 256 , 8/16/32 RW */ + +#define VLDBUF_BASE_ADDR (0xD80F1000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define IQ_BASE_ADDR (0xD80F1400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define IDCT_BASE_ADDR (0xD80F1800 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define STREAMIN_BASE_ADDR (0xD80F2000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define MSVD_BASE_ADDR (0xD80F3000 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define AVBO_FIFO_BASE_ADDR (0xD80F3400 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ +#define SPU_FIFO_BASE_ADDR (0xD80F3800 + WMT_MMAP_OFFSET) /* 1K , 8/16/32 RW */ + +#define TSIN0_BASE_ADDR (0xD80F4000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ +#define TSIN1_BASE_ADDR (0xD80F5000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ +#define TSIN2_BASE_ADDR (0xD80F6000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ +#define TSOUT_BASE_ADDR (0xD80F7000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ +#define H264_DECODER_BASE_ADDR (0xD80F8000 + WMT_MMAP_OFFSET) /* 16K , 8/16/32 RW */ + +#define CNM_BIT_BASE_ADDR (0xD80FC000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ + +#define JPEG_DECODER_BASE_ADDR (0xD80FE000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ +#define JPEG_ENCODER_BASE_ADDR (0xD80FF000 + WMT_MMAP_OFFSET) /* 4K , 8/16/32 RW */ + +/** + * Internal APB Slaves Memory Address Map + */ +#define RTC_BASE_ADDR (0xD8100000 + WMT_MMAP_OFFSET) /* 64K */ +#define GPIO_BASE_ADDR (0xD8110000 + WMT_MMAP_OFFSET) /* 64K */ +#define SYSTEM_CFG_CTRL_BASE_ADDR (0xD8120000 + WMT_MMAP_OFFSET) /* 64K */ +#define PM_CTRL_BASE_ADDR (0xD8130000 + WMT_MMAP_OFFSET) /* 64K */ +#define INTERRUPT0_CTRL_BASE_ADDR (0xD8140000 + WMT_MMAP_OFFSET) /* 64K */ +#define INTERRUPT1_CTRL_BASE_ADDR (0xD8150000 + WMT_MMAP_OFFSET) /* 64K */ + +#define AUDIO_CODEC_BASE_ADDR (0xD81F0000 + WMT_MMAP_OFFSET) /* 64K */ +#define UART0_BASE_ADDR (0xD8200000 + WMT_MMAP_OFFSET) /* 64K */ +#define UART1_BASE_ADDR (0xD82b0000 + WMT_MMAP_OFFSET) /* 64K */ +#define UART2_BASE_ADDR (0xD8210000 + WMT_MMAP_OFFSET) /* 64K */ +#define UART3_BASE_ADDR (0xD82c0000 + WMT_MMAP_OFFSET) /* 64K */ +#define UART4_BASE_ADDR (0xD8370000 + WMT_MMAP_OFFSET) /* 64K */ +#define UART5_BASE_ADDR (0xD8380000 + WMT_MMAP_OFFSET) /* 64K */ +#define PWM0_BASE_ADDR (0xD8220000 + WMT_MMAP_OFFSET) /* 64K */ + +#define SPI0_BASE_ADDR (0xD8240000 + WMT_MMAP_OFFSET) /* 64K */ +#define SPI1_BASE_ADDR (0xD8250000 + WMT_MMAP_OFFSET) /* 64K */ +#define SPI2_BASE_ADDR (0xD82A0000 + WMT_MMAP_OFFSET) /* 64K */ +#define KPAD_BASE_ADDR (0xD8260000 + WMT_MMAP_OFFSET) /* 64K */ +#define CIR_BASE_ADDR (0xD8270000 + WMT_MMAP_OFFSET) /* 64K */ +#define I2C0_BASE_ADDR (0xD8280000 + WMT_MMAP_OFFSET) /* 64K */ +#define I2C1_BASE_ADDR (0xD8320000 + WMT_MMAP_OFFSET) /* 64K */ +#define PCM_BASE_ADDR (0xD82D0000 + WMT_MMAP_OFFSET) /* 64K */ +#define AC97_BASE_ADDR (0xD8290000 + WMT_MMAP_OFFSET) /* 64K */ + +#define AHB_ACCESS_MONITOR0_BASE_ADDR (0xD82E0000 + WMT_MMAP_OFFSET) +#define AHB_ACCESS_MONITOR1_BASE_ADDR (0xD82F0000 + WMT_MMAP_OFFSET) +#define AHB_ACCESS_MONITOR2_BASE_ADDR (0xD8300000 + WMT_MMAP_OFFSET) +#define AHB_ACCESS_MONITOR3_BASE_ADDR (0xD8310000 + WMT_MMAP_OFFSET) + +#define ADC_BASE_ADDR (0xD8340000 + WMT_MMAP_OFFSET) /* 64K */ +#define ROTARY_DETECTOR_BASE_ADDR (0xD8350000 + WMT_MMAP_OFFSET) /* 64K */ +#define SMART_CARD_INTERFACE_BASE_ADDR (0xD8360000 + WMT_MMAP_OFFSET) /* 64K */ +#define POWER_MOS_BASE_ADDR (0xD8390000 + WMT_MMAP_OFFSET) /* 64K */ +// check +#define MEMORY_CTRL_CFG_BASE_ADDR MEMORY_CTRL_V3_CFG_BASE_ADDR +#define DMA_CTRL_CFG_BASE_ADDR DMA_CTRL_V4_CFG_BASE_ADDR +#define LPC_CTRL_CFG_BASE_ADDR LPC_SUPERIO_CFG_BASE_ADDR +#define HDMI1_BASE_ADDR (0xD806C000 + WMT_MMAP_OFFSET) +#define HDMI2_BASE_ADDR (0xD8070000 + WMT_MMAP_OFFSET) +#define GOVR_BASE_ADDR (0xD8050B00 + WMT_MMAP_OFFSET) +#define INTERRUPT_CTRL_BASE_ADDR INTERRUPT0_CTRL_BASE_ADDR +#define SPI_BASE_ADDR SPI0_BASE_ADDR +#define I2C_BASE_ADDR I2C0_BASE_ADDR +#define I2S_BASE_ADDR AUDREGF_BASE_ADDR + + +/* WMT Memory Map for Physical Address*/ +#define UART0_PHY_BASE_ADDR 0xD8200000 /* 64K */ +#define UART1_PHY_BASE_ADDR 0xD82b0000 /* 64K */ + +#endif /* __WMT_MMAP_H */ diff --git a/common/wmt_display/hw_devices.h b/common/wmt_display/hw_devices.h new file mode 100755 index 0000000..7ba39c8 --- /dev/null +++ b/common/wmt_display/hw_devices.h @@ -0,0 +1,38 @@ +/*++ + * linux/drivers/video/wmt/govm.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2010 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef HW_DEVICES_H +#define HW_DEVICES_H + +int sil902x_module_init(void); +int vt1632_module_init(void); +int vt1625_module_init(void); +int lcd_module_init(void); +int lcd_oem_init(void); +int lcd_at070tn83_init(void); +int lcd_a080sn01_init(void); +int lcd_lw700at9003_init(void); +int lcd_ek08009_init(void); +int lcd_HSD101PFW2_init(void); +int lcd_LVDS_1024x600_init(void); +#endif diff --git a/common/wmt_display/lcd.h b/common/wmt_display/lcd.h new file mode 100755 index 0000000..09acea0 --- /dev/null +++ b/common/wmt_display/lcd.h @@ -0,0 +1,105 @@ +/*++ + * linux/drivers/video/wmt/lcd.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef LCD_H +/* To assert that only one occurrence is included */ +#define LCD_H +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ +#include "vpp.h" + +/* following is the C++ header */ +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* #define LCD_XXXX 1 *//*Example*/ + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void lcd_xxx_t; *//*Example*/ +enum lcd_panel_t { + LCD_WMT_OEM, + LCD_CHILIN_LW0700AT9003, + LCD_INNOLUX_AT070TN83, + LCD_AUO_A080SN01, + LCD_EKING_EK08009, + LCD_HANNSTAR_HSD101PFW2, + LCD_LVDS_1024x600, + LCD_B079XAN01, + LCD_TPO_TJ015NC02AA, + LCD_BP080WX7, + LCD_PANEL_MAX +}; + +#define LCD_CAP_CLK_HI BIT(0) +#define LCD_CAP_HSYNC_HI BIT(1) +#define LCD_CAP_VSYNC_HI BIT(2) +#define LCD_CAP_DE_LO BIT(3) +struct lcd_parm_t { + int bits_per_pixel; + unsigned int capability; + struct fb_videomode vmode; + int width; /* width of picture in mm */ + int height; /* height of picture in mm */ + + void (*initial)(void); + void (*uninitial)(void); +}; + +/*-------------------- EXPORTED PRIVATE VARIABLES ---------------------------*/ +#ifdef LCD_C /* allocate memory for variables only in vout.c */ +#define EXTERN +#else +#define EXTERN extern +#endif /* ifdef LCD_C */ + +/* EXTERN int lcd_xxx; *//*Example*/ + +EXTERN struct lcd_parm_t *p_lcd; +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS ------------------------------*/ +/* #define LCD_XXX_YYY xxxx *//*Example*/ +/*--------------------- EXPORTED PRIVATE FUNCTIONS --------------------------*/ +/* extern void lcd_xxx(void); *//*Example*/ + +int lcd_panel_register(int no, void (*get_parm)(int mode)); +struct lcd_parm_t *lcd_get_parm(enum lcd_panel_t id, unsigned int arg); +void lcd_set_parm(int id, int bpp); +struct lcd_parm_t *lcd_get_oem_parm(int resx, int resy); +void lcd_set_lvds_id(int id); +int lcd_get_lvds_id(void); +void lcd_set_type(int type); +int lcd_get_type(void); +void lcd_set_enable(int enable); +void lcd_enable_signal(int enable); + +#ifdef CONFIG_VPP_SHENZHEN +void lcd_backlight_power_on(int on); +#endif + +/* LCD back light */ +#ifdef __cplusplus +} +#endif +#endif /* ifndef LCD_H */ diff --git a/common/wmt_display/lvds.c b/common/wmt_display/lvds.c new file mode 100755 index 0000000..2516d78 --- /dev/null +++ b/common/wmt_display/lvds.c @@ -0,0 +1,202 @@ +/*++ + * linux/drivers/video/wmt/lvds.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define LVDS_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "lvds.h" + +#ifdef WMT_FTBLK_LVDS +/*----------------------- PRIVATE MACRO --------------------------------------*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LVDS_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lvds_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lvds.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lvds_xxx; *//*Example*/ +struct lvds_base_regs *lvds_regs = (void *) LVDS_BASE_ADDR; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lvds_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +void lvds_set_power_down(int pwrdn) +{ + DBG_DETAIL("(%d)\n", pwrdn); + + lvds_regs->test.b.pd = pwrdn; + mdelay(1); + lvds_regs->test2.b.pd_l2ha = pwrdn; +} + +void lvds_set_enable(vpp_flag_t enable) +{ + DBG_DETAIL("(%d)\n", enable); + lvds_regs->test.b.tre_en = (enable) ? 0 : 1; + lvds_regs->test2.b.mode = (enable) ? 1 : 0; + lvds_regs->test2.b.resa_en = (enable) ? 0 : 1; +#ifdef CONFIG_UBOOT + if ((enable) && (lcd_get_lvds_id() == LCD_LVDS_1024x600)) { + /* GPIO10 VDD_EN->CLK delay 16->38ms */ + outl(inl(GPIO_BASE_ADDR + 0x80) | BIT10, GPIO_BASE_ADDR + 0x80); + outl(inl(GPIO_BASE_ADDR + 0xC0) | BIT10, GPIO_BASE_ADDR + 0xC0); + mdelay(16); + } +#endif +} + +int lvds_get_enable(void) +{ + return lvds_regs->test2.b.mode; +} + +void lvds_set_rgb_type(int bpp) +{ + int mode; + int mode_change = 0x2; + + DBG_DETAIL("(%d)\n", bpp); + + /* 0:888, 1-555, 2-666, 3-565 */ + switch (bpp) { + case 15: + mode = 1; + break; + case 16: + mode = 3; + break; + case 18: + mode = 2; + break; + case 24: + default: + mode = 0; + mode_change = 0x0; + break; + } +#if 1 /* IGS default */ + mode = 4; +#endif + lvds_regs->status.b.test = mode_change; + lvds_regs->igs.b.bpp_type = mode; +} + +vdo_color_fmt lvds_get_colfmt(void) +{ + return VDO_COL_FMT_ARGB; +} + +void lvds_set_sync_polar(int h_lo, int v_lo) +{ + DBG_DETAIL("(%d,%d)\n", h_lo, v_lo); + lvds_regs->set.b.hsync_polar_lo = h_lo; + lvds_regs->set.b.vsync_polar_lo = v_lo; +} + +void lvds_get_sync_polar(int *hsync_hi, int *vsync_hi) +{ + *hsync_hi = (lvds_regs->set.b.hsync_polar_lo) ? 0 : 1; + *vsync_hi = (lvds_regs->set.b.vsync_polar_lo) ? 0 : 1; +} + +/*----------------------- Module API --------------------------------------*/ +void lvds_reg_dump(void) +{ + DPRINT("========== LVDS register dump ==========\n"); + vpp_reg_dump(REG_LVDS_BEGIN, REG_LVDS_END-REG_LVDS_BEGIN); + + DPRINT("---------- LVDS common ----------\n"); + DPRINT("test %d,dual chan %d,inv clk %d\n", lvds_regs->status.b.test, + lvds_regs->status.b.dual_channel, lvds_regs->status.b.inv_clk); + DPRINT("ldi shift left %d,IGS bpp type %d\n", + lvds_regs->igs.b.ldi_shift_left, lvds_regs->igs.b.bpp_type); + DPRINT("rsen %d,pll ready %d\n", lvds_regs->detect.b.rsen, + lvds_regs->detect.b.pll_ready); + DPRINT("pwr dn %d\n", lvds_regs->test.b.pd); +} + +#ifdef CONFIG_PM +static unsigned int *lvds_pm_bk; +static unsigned int lvds_pd_bk; +void lvds_suspend(int sts) +{ + switch (sts) { + case 0: /* disable module */ + break; + case 1: /* disable tg */ + break; + case 2: /* backup register */ + lvds_pd_bk = lvds_regs->test.b.pd; + lvds_set_power_down(1); + lvds_pm_bk = vpp_backup_reg(REG_LVDS_BEGIN, + (REG_LVDS_END-REG_LVDS_BEGIN)); + break; + default: + break; + } +} + +void lvds_resume(int sts) +{ + switch (sts) { + case 0: /* restore register */ + vpp_restore_reg(REG_LVDS_BEGIN, + (REG_LVDS_END-REG_LVDS_BEGIN), lvds_pm_bk); + lvds_pm_bk = 0; + if (lcd_get_lvds_id() != LCD_LVDS_1024x600) + lvds_set_power_down(lvds_pd_bk); + break; + case 1: /* enable module */ + break; + case 2: /* enable tg */ + break; + default: + break; + } +} +#else +#define lvds_suspend NULL +#define lvds_resume NULL +#endif + +void lvds_init(void) +{ + lvds_regs->level.b.level = 1; + lvds_regs->level.b.update = 1; + lvds_regs->test.b.pll_r_f = 1; + lvds_regs->test.b.pll_cpset = 1; + lvds_regs->test.b.tre_en = 0; + lvds_regs->test.b.vbg_sel = 2; + lvds_regs->test.b.drv_pdmode = 0; + lvds_regs->igs.b.ldi_shift_left = 1; + lvds_regs->test2.val = 0x31432; +} + +#endif /* WMT_FTBLK_LVDS */ + diff --git a/common/wmt_display/lvds.h b/common/wmt_display/lvds.h new file mode 100755 index 0000000..9821a66 --- /dev/null +++ b/common/wmt_display/lvds.h @@ -0,0 +1,73 @@ +/*++ + * linux/drivers/video/wmt/lvds.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include "vpp.h" + +#ifndef LVDS_H +/* To assert that only one occurrence is included */ +#define LVDS_H +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ + +/* following is the C++ header */ +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* #define LVDS_XXXX 1 *//*Example*/ + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void lvds_xxx_t; *//*Example*/ + +/*-------------------- EXPORTED PRIVATE VARIABLES ----------------------------*/ +#ifdef LVDS_C +#define EXTERN +#else +#define EXTERN extern +#endif /* ifdef LVDS_C */ + +/* EXTERN int lvds_xxx; *//*Example*/ + +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS ------------------------------*/ +/* #define LVDS_XXX_YYY xxxx *//*Example*/ +/*--------------------- EXPORTED PRIVATE FUNCTIONS --------------------------*/ +/* extern void lvds_xxx(void); *//*Example*/ +void lvds_set_enable(vpp_flag_t enable); +int lvds_get_enable(void); +void lvds_set_rgb_type(int bpp); +vdo_color_fmt lvds_get_colfmt(void); +void lvds_reg_dump(void); +void lvds_suspend(int sts); +void lvds_resume(int sts); +void lvds_init(void); +void lvds_set_power_down(int pwrdn); +void lvds_set_sync_polar(int h_lo, int v_lo); +void lvds_get_sync_polar(int *hsync_hi, int *vsync_hi); + +#ifdef __cplusplus +} +#endif +#endif /* ifndef LVDS_H */ + diff --git a/common/wmt_display/minivgui.c b/common/wmt_display/minivgui.c new file mode 100755 index 0000000..54820dd --- /dev/null +++ b/common/wmt_display/minivgui.c @@ -0,0 +1,1949 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> +#include <bmp_layout.h> + +#include "wmt_display.h" +#include "minivgui.h" + +#define CHARGEANIM_PIC_NUM 7 // 1 big picture include 7 small pictures + +static char *sp_free_addr = (char *)5000000; + +static int s_display_percent; +static int s_percent_val = -1; + +int g_tf_boot; // system boot from tf card. If set to 1, it means boot from eMMC. Otherwise, boot from Nand Flash + +typedef unsigned short GlyphScatter; + +#define Memcpy(dest, src, n) memcpy(dest, src, n) + +extern void *arm_memcpy(void *dest, const void *src, size_t n); +extern void *arm_memset(void *s, int c, size_t count); +extern void lcd_blt_enable(int no, int enable); + +typedef struct { + unsigned short ucs2Start; + unsigned short ucs2End; +} GlyphRange; + +// +// ×ÖÌåÎļþ²¼¾Ö +// ---------------- +// | ÎļþÍ· | // FontFileHead +// ---------------| +// | Çø¼äÐÅÏ¢Êý×é | // Á¬ÐøÇø¼äÊý¾Ý GlyphRange[] +// ---------------- +// | ÀëÉ¢ÐÅÏ¢Êý×é | // ÀëÉ¢µãÊý¾Ý GlyphScatter[] ÒѾÅÅÐò +// ---------------| +// | missingµãÕó | // missing glyph µãÕ󣬶îÍâµÄÒ»¸öµãÕóÓÃÓÚÏÔʾÎÞ·¨ÕÒµ½µÄ×Ö·û +// ---------------- +// | Çø¼ä1µãÕó | // Á¬ÐøÇø¼äµãÕóÊý¾Ý +// | Çø¼ä2µãÕó | // Á¬ÐøÇø¼äµãÕóÊý¾Ý +// | Çø¼ä... | // Á¬ÐøÇø¼äµãÕóÊý¾Ý +// ---------------- +// | ÀëÉ¢1µãÕó | // ÀëÉ¢µÄµãÕó +// | ÀëÉ¢2µãÕó | // ÀëÉ¢µÄµãÕó +// | ÀëÉ¢... | // ÀëÉ¢µÄµãÕó +// ---------------- + +static const unsigned char s_fontData[] = { + 0x46, 0x54, 0x02, 0x10, 0x46, 0x6F, 0x6E, 0x74, 0x20, 0x31, 0x32, 0x78, 0x32, 0x32, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0C, 0x16, 0x2C, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x80, 0x10, 0x80, 0x10, + 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x10, + 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39, 0xC0, 0x39, 0xC0, + 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x04, 0x80, 0x04, 0x80, 0x09, 0x00, + 0x09, 0x00, 0x3F, 0xC0, 0x09, 0x00, 0x09, 0x00, 0x3F, 0xC0, 0x09, 0x00, 0x09, 0x00, 0x12, 0x00, + 0x12, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0F, 0x80, 0x10, 0x80, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, + 0x1E, 0x00, 0x01, 0x80, 0x00, 0x80, 0x20, 0x80, 0x21, 0x80, 0x3F, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x22, 0x00, 0x22, 0x00, 0x22, 0x00, 0x1C, 0x00, 0x01, 0x80, 0x0E, 0x00, 0x30, 0x00, + 0x07, 0x00, 0x08, 0x80, 0x08, 0x80, 0x08, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x3F, 0x80, 0x04, 0x00, 0x06, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x7F, 0xC0, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, + 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x10, 0x80, 0x10, 0x80, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, + 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x80, 0x10, 0x80, 0x0F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x3A, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x10, 0x80, + 0x20, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x10, 0x00, 0x20, 0x40, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x30, 0x80, 0x00, 0x40, 0x00, 0x40, + 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x20, 0x80, + 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03, 0x00, 0x03, 0x00, 0x05, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x11, 0x00, 0x11, 0x00, 0x21, 0x00, 0x3F, 0x80, 0x01, 0x00, 0x01, 0x00, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x80, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x17, 0x00, 0x18, 0x80, 0x00, 0x40, + 0x00, 0x40, 0x00, 0x40, 0x20, 0x40, 0x10, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x06, 0x00, + 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x27, 0x80, 0x28, 0x40, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x10, 0x20, 0x08, 0x40, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x20, 0x40, 0x00, 0x40, 0x00, 0x80, + 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x11, 0x00, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x11, 0x00, + 0x0F, 0x00, 0x11, 0x00, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x11, 0x00, 0x0E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x11, 0x80, 0x20, 0x80, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x10, 0xC0, 0x0F, 0x40, + 0x00, 0x40, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x0C, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x03, 0x00, 0x0C, 0x00, + 0x10, 0x00, 0x60, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, + 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x10, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x03, 0x00, + 0x0C, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x10, 0x80, 0x10, 0x40, + 0x00, 0x40, 0x00, 0x40, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x18, 0x80, 0x20, 0x40, 0x20, 0x40, 0x21, 0xC0, 0x22, 0x40, + 0x24, 0x40, 0x24, 0x40, 0x24, 0x40, 0x23, 0xC0, 0x20, 0x00, 0x20, 0x00, 0x10, 0x80, 0x0F, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3E, 0x00, 0x06, 0x00, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, 0x10, 0x80, 0x10, 0x80, + 0x3F, 0xC0, 0x20, 0x40, 0x20, 0x40, 0x40, 0x20, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, + 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x80, 0x1F, 0x80, 0x10, 0x40, 0x10, 0x20, 0x10, 0x20, + 0x10, 0x20, 0x10, 0x40, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x20, 0x10, 0xE0, 0x20, 0x20, + 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x20, 0x20, 0x10, 0x40, + 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x10, 0x40, 0x10, 0x40, 0x10, 0x20, 0x10, 0x20, + 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x10, 0x40, 0x10, 0x40, 0x3F, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7F, 0xE0, 0x10, 0x20, 0x10, 0x20, 0x11, 0x00, 0x11, 0x00, 0x1F, 0x00, 0x11, 0x00, + 0x11, 0x00, 0x10, 0x20, 0x10, 0x20, 0x10, 0x20, 0x7F, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xE0, + 0x10, 0x20, 0x10, 0x20, 0x11, 0x00, 0x11, 0x00, 0x1F, 0x00, 0x11, 0x00, 0x11, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x40, 0x10, 0xC0, 0x20, 0x40, + 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x43, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x20, 0x40, 0x10, 0x40, + 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xF0, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, + 0x3F, 0xC0, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0xF9, 0xF0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3F, 0x80, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, + 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, + 0x20, 0x80, 0x11, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xF0, 0x10, 0x40, 0x10, 0x80, + 0x11, 0x00, 0x12, 0x00, 0x14, 0x00, 0x1E, 0x00, 0x11, 0x00, 0x10, 0x80, 0x10, 0x80, 0x10, 0x40, + 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x08, 0x20, 0x3F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xE0, 0xE0, 0x60, 0xC0, 0x51, 0x40, 0x51, 0x40, 0x51, 0x40, 0x4A, 0x40, 0x4A, 0x40, + 0x44, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xE0, + 0x30, 0x40, 0x28, 0x40, 0x28, 0x40, 0x24, 0x40, 0x24, 0x40, 0x22, 0x40, 0x22, 0x40, 0x21, 0x40, + 0x21, 0x40, 0x20, 0xC0, 0x70, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x10, 0x80, 0x20, 0x40, + 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x20, 0x40, 0x10, 0x80, + 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x10, 0x80, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, + 0x10, 0x80, 0x1F, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0F, 0x00, 0x10, 0x80, 0x20, 0x40, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, + 0x40, 0x20, 0x40, 0x20, 0x20, 0x40, 0x10, 0x80, 0x0F, 0x00, 0x04, 0x00, 0x0F, 0x20, 0x18, 0xC0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x00, + 0x10, 0x80, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x80, 0x1F, 0x00, 0x10, 0x80, 0x10, 0x40, + 0x10, 0x40, 0x10, 0x20, 0x78, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x40, 0x10, 0xC0, 0x20, 0x40, + 0x20, 0x00, 0x30, 0x00, 0x0F, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x40, 0x20, 0x40, 0x30, 0x80, + 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x44, 0x40, 0x44, 0x40, 0x44, 0x40, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x70, 0xE0, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, + 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x10, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, + 0x20, 0x40, 0x20, 0x40, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x09, 0x00, 0x09, 0x00, 0x09, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xF0, 0x40, 0x40, 0x40, 0x40, + 0x44, 0x40, 0x44, 0x40, 0x24, 0x80, 0x2A, 0x80, 0x2A, 0x80, 0x2A, 0x80, 0x2A, 0x80, 0x2A, 0x80, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF1, 0xE0, 0x20, 0x80, 0x11, 0x00, 0x11, 0x00, 0x0A, 0x00, + 0x04, 0x00, 0x0A, 0x00, 0x11, 0x00, 0x10, 0x80, 0x20, 0x80, 0x40, 0x40, 0xF1, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x78, 0xF0, 0x20, 0x20, 0x10, 0x40, 0x08, 0x80, 0x05, 0x00, 0x05, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, + 0x20, 0x40, 0x20, 0x80, 0x21, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x08, 0x40, + 0x10, 0x40, 0x20, 0x40, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x80, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x3C, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x09, 0x00, 0x09, 0x00, 0x10, 0x80, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x10, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x0F, 0xC0, 0x10, 0x40, 0x20, 0x40, 0x20, 0xC0, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x27, 0x80, 0x28, 0x40, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x20, 0x28, 0x40, 0x67, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0xA0, 0x10, 0x60, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x20, 0x10, 0x40, + 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x1E, 0x40, 0x21, 0xC0, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, 0xC0, 0x1E, 0x60, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x10, 0x80, 0x20, 0x40, 0x20, 0x40, + 0x3F, 0xC0, 0x20, 0x00, 0x20, 0x00, 0x10, 0x40, 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x3F, 0x80, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0E, 0xC0, 0x11, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x20, 0x80, 0x11, 0x80, + 0x0E, 0x80, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x17, 0x00, 0x18, 0x80, + 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x38, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x3E, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x11, 0xE0, 0x10, 0x80, 0x13, 0x00, 0x14, 0x00, 0x1C, 0x00, 0x12, 0x00, 0x11, 0x00, 0x10, 0x80, + 0x31, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x3F, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xC0, 0x33, 0x20, 0x22, 0x20, 0x22, 0x20, + 0x22, 0x20, 0x22, 0x20, 0x22, 0x20, 0x22, 0x20, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x18, 0x80, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, 0x10, 0x40, + 0x10, 0x40, 0x10, 0x40, 0x38, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0F, 0x80, 0x10, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x40, + 0x0F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x80, 0x28, 0x40, + 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, 0x28, 0x40, 0x27, 0x80, 0x20, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x60, 0x21, 0x40, 0x40, 0xC0, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, 0xC0, 0x1E, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x19, 0xC0, 0x0A, 0x20, 0x0C, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x40, 0x20, 0xC0, 0x20, 0x40, 0x1F, 0x00, 0x00, 0x80, 0x00, 0x40, 0x20, 0x40, 0x30, 0x80, + 0x2F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x3F, 0xC0, 0x08, 0x00, + 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x60, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0xC0, 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, + 0x20, 0x40, 0x20, 0x40, 0x20, 0x40, 0x20, 0xC0, 0x1F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x20, 0x40, 0x10, 0x80, 0x10, 0x80, 0x10, 0x80, 0x09, 0x00, + 0x09, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0xF0, 0x40, 0x40, 0x44, 0x40, 0x44, 0x40, 0x24, 0x80, 0x2A, 0x80, 0x2A, 0x80, 0x2A, 0x80, + 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xE0, 0x20, 0x40, + 0x10, 0x80, 0x09, 0x00, 0x06, 0x00, 0x09, 0x00, 0x10, 0x80, 0x20, 0x40, 0x79, 0xE0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0x20, 0x40, 0x20, 0x80, 0x10, 0x80, + 0x10, 0x80, 0x09, 0x00, 0x09, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x20, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, + 0x10, 0x00, 0x20, 0x40, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0C, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, + 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, + 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x26, 0x40, 0x01, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/** + * the VGUI private Font file version 1.0 head struct, internally used only. + */ +typedef struct { + char magic[2]; // "FT" + unsigned short version; // 0x1001 (1.01) + + char name[32]; // description + + unsigned char charWidth; + unsigned char charHeight; + unsigned short glyphBytes; + + unsigned short rangeCount; + unsigned short scatterCount; +} FontFileHeadV1; + + +static mv_surface s_surface[5]; + +unsigned int (*rgb2color)(unsigned char r, unsigned char g, unsigned char b); +void (*putcolor2fb)(const mv_surface *s, int x, int y, unsigned int color); +void (*putcolor2mem)(const mv_surface *s, int x, int y, unsigned int color); + +static unsigned char *m_fileStart; +static unsigned char *m_glyphStart; +static FontFileHeadV1 *m_fh; +int bitsPerPixel; + +//Display Direction definition: +// 0: portrait, the back button under the screen ( ÊúÆÁ, back ¼üÔÚÏÂ) +// 1: landscape, the back button on the right of the screnn ( ºáÆÁ, back¼üÔÚÓÒ) +// 2: portrait, the back button above the screen ( ÊúÆÁ, back¼üÔÚÉÏ) +// 3: landscape, the back button on the left of the screen ( ºáÆÁ, back¼üÔÚ×ó) +int g_display_direction = 1; + +// for mem aligment +extern void byte1_alig_mem_copy(char *src, char *des, unsigned int len); +extern void byte2_alig_mem_copy(char *src, char *des, unsigned int len); +extern void byte3_alig_mem_copy(char *src, char *des, unsigned int len); +extern void mem_copy(char *src, char *des, unsigned int len); +extern void byte1_less_bundle_copy(char *src, char *des, unsigned int len); +extern void byte2_less_bundle_copy(char *src, char *des, unsigned int len); +extern void byte3_less_bundle_copy(char *src, char *des, unsigned int len); +extern void less_mem_copy(char *src, char *des, unsigned int len); + +// 24bits bitmap -> 146bits frame buffer +extern void bit24_to_bit16_ali24(char *src, char *des, unsigned int len); +extern void bit24_to_bit16_ali32(char *src, char *des, unsigned int len); + +static int setFontFileDat(const unsigned char *dat); + +static unsigned int rgb2color565(unsigned char r, unsigned char g, unsigned char b) +{ + unsigned int ret = 0; + ret = (unsigned int)(((r) >> 3) << 11 | ((g) >> 2) << 5 | ((b) >> 3)); + return ret; +} +/* +static unsigned int rgb2color555(unsigned char r, unsigned char g, unsigned char b) +{ + unsigned int ret = 0; + ret = (unsigned int)((((r) >> 3) << 10 | ((g) >> 3) << 5 | ((b) >> 3)) & 0x7fff); + return ret; +} +*/ +static unsigned int rgb2color888(unsigned char r, unsigned char g, unsigned char b) +{ + unsigned int ret = 0; + ret = (unsigned int)(((r) << 16 | (g) << 8 | (b)) & 0x00FFFFFF); + return ret; +} +/* +static unsigned int rgb2color666(unsigned char r, unsigned char g, unsigned char b) +{ + unsigned int ret = 0; + ret = (unsigned int)(((r) >> 2) << 12 | ((g) >> 2) << 6 | ((b) >> 2)); + return ret; +} +*/ + +static void putcolor2fb16(const mv_surface *s, int x, int y, unsigned int color) +{ + if(g_display_direction == 1) { + if((g_logo_scale != LOGO_NOT_SCALE) || (x >= 0 && x < s->width && y >= 0 && y < s->height)) + *(unsigned short *)(s->startAddr + (x * 2) + (s->lineBytes * y)) = (unsigned short)color; + } else { //circumrotate the font + int new_x, new_y; + + new_x = x; + new_y = y; + + switch(g_display_direction) { + case 0: + new_x = y; + new_y = (s->height - 1 - x); + break; + + case 2: + new_x = (s->width - 1 - y); + new_y = x; + break; + + case 3: + new_x = (s->width - 1 - x); + new_y = (s->height - 1 - y); + break; + } + + if((g_logo_scale != LOGO_NOT_SCALE) || (new_x >= 0 && new_x < s->width && new_y >= 0 && new_y < s->height)) + *(unsigned short *)(s->startAddr + (new_x * 2) + (s->lineBytes * new_y)) = (unsigned short)color; + } +} + +static void putcolor2fb32(const mv_surface *s, int x, int y, unsigned int color) +{ + if(g_display_direction == 1) { + if((g_logo_scale != LOGO_NOT_SCALE) || (x >= 0 && x < s->width && y >= 0 && y < s->height)) + *(unsigned int *)(s->startAddr + (x * 4) + (s->lineBytes * y)) = (unsigned int)color; + } else { //circumrotate the font + int new_x, new_y; + + new_x = x; + new_y = y; + + switch(g_display_direction) { + case 0: + new_x = y; + new_y = (s->height - 1 - x); + break; + + case 2: + new_x = (s->width - 1 - y); + new_y = x; + break; + + case 3: + new_x = (s->width - 1 - x); + new_y = (s->height - 1 - y); + break; + } + + if((g_logo_scale != LOGO_NOT_SCALE) || (new_x >= 0 && new_x < s->width && new_y >= 0 && new_y < s->height)) + *(unsigned int *)(s->startAddr + (new_x * 4) + (s->lineBytes * new_y)) = (unsigned int)color; + } +} + +mv_surface *mv_getSurface(int no) +{ + return &s_surface[no]; +} + +static void putcolor2mem16(const mv_surface *s, int x, int y, unsigned int color) +{ + if(g_display_direction == 1) { + if((g_logo_scale != LOGO_NOT_SCALE) || (x >= 0 && x < s->width && y >= 0 && y < s->height)) + *(unsigned short *)(sp_free_addr + (x * 2) + (s->lineBytes * y)) = (unsigned short)color; + } else { //circumrotate the font + int new_x, new_y; + + new_x = x; + new_y = y; + + switch(g_display_direction) { + case 0: + new_x = y; + new_y = (s->height - 1 - x); + break; + + case 2: + new_x = (s->width - 1 - y); + new_y = x; + break; + + case 3: + new_x = (s->width - 1 - x); + new_y = (s->height - 1 - y); + break; + } + + if((g_logo_scale != LOGO_NOT_SCALE) || (new_x >= 0 && new_x < s->width && new_y >= 0 && new_y < s->height)) + *(unsigned short *)(sp_free_addr + (new_x * 2) + (s->lineBytes * new_y)) = (unsigned short)color; + } +} + +static void putcolor2mem32(const mv_surface *s, int x, int y, unsigned int color) +{ + if(g_display_direction == 1) { + if((g_logo_scale != LOGO_NOT_SCALE) || (x >= 0 && x < s->width && y >= 0 && y < s->height)) + *(unsigned int *)(sp_free_addr + (x * 4) + (s->lineBytes * y)) = (unsigned int)color; + } else { //circumrotate the font + int new_x, new_y; + + new_x = x; + new_y = y; + + switch(g_display_direction) { + case 0: + new_x = y; + new_y = (s->height - 1 - x); + break; + + case 2: + new_x = (s->width - 1 - y); + new_y = x; + break; + + case 3: + new_x = (s->width - 1 - x); + new_y = (s->height - 1 - y); + break; + } + + if((g_logo_scale != LOGO_NOT_SCALE) || (new_x >= 0 && new_x < s->width && new_y >= 0 && new_y < s->height)) + *(unsigned int *)(sp_free_addr + (new_x * 4) + (s->lineBytes * new_y)) = (unsigned int)color; + } +} + +static int get_fb_offset(const mv_surface *s, int img_width, int img_height, int xpos, int ypos) +{ + int x, y; + int bytes_per_pixel; + + bytes_per_pixel = (s->bits_per_pixel >> 3); + + switch(g_display_direction) { + case 0: + x = ypos; + y = s->height - xpos - img_width; + break; + + case 2: + x = s->width - ypos - img_height; + y = xpos; + break; + + case 3: + x = s->width - xpos - img_width; + y = s->height - ypos - img_height; + break; + + case 1: + default: + x = xpos; + y = ypos; + break; + } + + return (x * bytes_per_pixel + s->lineBytes * y); +} + +static void mem2fb(const mv_surface *s, int width, int height, int xpos, int ypos) +{ + int new_width, new_height, new_xpos, new_ypos; + int i, bytes_per_pixel, fb_offset; + char *dest, *src; + + new_width = width; + new_height = height; + new_xpos = xpos; + new_ypos = ypos; + bytes_per_pixel = (s->bits_per_pixel >> 3); + + switch(g_display_direction) { + case 0: // the screen is portrait + case 2: + new_width = height; + new_height = width; + new_xpos = ypos; + new_ypos = xpos; + break; + } + + fb_offset = get_fb_offset(s, width, height, xpos, ypos); + dest = s->startAddr + fb_offset; + src = sp_free_addr + fb_offset; + + for (i = 0; i < new_height; i++) { + arm_memcpy(dest, src, new_width * bytes_per_pixel); + dest += s->lineBytes; + src += s->lineBytes; + } +} + +void mv_clearFB(void) +{ + int no; + mv_surface *s; + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = &s_surface[no]; + if(s->startAddr) + arm_memset(s->startAddr, 0, s->height * s->lineBytes); + } +} + +void mv_initSurface(int no, const mv_surface *s) +{ + static int flag = 0; + unsigned int free_addr; + + Memcpy(&s_surface[no], s, sizeof(mv_surface)); + if (flag == 0) { + setFontFileDat(s_fontData); //defined in "fontdata.h" + if (s->bits_per_pixel == 16) { + rgb2color = rgb2color565; + putcolor2fb = putcolor2fb16; + putcolor2mem = putcolor2mem16; + bitsPerPixel = 16; + } else { + rgb2color = rgb2color888; + putcolor2fb = putcolor2fb32; + putcolor2mem = putcolor2mem32; + } + + free_addr = (unsigned int)s->startAddr - (1920 * 1080 * 4) * 2; + if(free_addr < 0) + free_addr = 0; + + sp_free_addr = (char *)free_addr; + + flag = 1; + } +} + +void check_display_direction(void) +{ + char *env; + + env = getenv("wmt.org.direction"); + if (!env) { + g_display_direction = 1; + } else { + g_display_direction = simple_strtoul(env, NULL, 10); + if(g_display_direction < 0 || g_display_direction > 3) + g_display_direction = 1; + } + + //printf("display direction %d\n", g_display_direction); +} + +void check_tf_boot(void) +{ + char *env; + + env = getenv("wmt.boot.dev"); + if (env && !strnicmp(env, "TF", 2)) + g_tf_boot = 1; +} + +void mv_dumpSurface(void) +{ + printf("s_surface[0]: width = %d, height = %d, lineBytes = %d, bits_per_pixel = %d, startAddr = 0x%p\n", + s_surface[0].width, s_surface[0].height, s_surface[0].lineBytes, s_surface[0].bits_per_pixel, s_surface[0].startAddr); + + printf("s_surface[1]: width = %d, height = %d, lineBytes = %d, bits_per_pixel = %d, startAddr = 0x%p\n", + s_surface[1].width, s_surface[1].height, s_surface[1].lineBytes, s_surface[1].bits_per_pixel, s_surface[1].startAddr); +} + +void mv_drawLine(int no, int x1, int y1, int x2, int y2, unsigned int color) +{ + int i; + //mv_color* p; + const mv_surface *s = &s_surface[no]; + + if ( y1 == y2 ) { + if (x1 > x2) { + int tmp = x1; + x1 = x2; + x2 = tmp; + } +#if 0 + // horz line + p = getXYData(s, x1, y1); + for (i = x1; i < x2; ++i) + *p++ = color; +#else + for (i = x1; i < x2; ++i) + putcolor2fb(s, i, y1, color); +#endif + } else if ( x1 == x2 ) { + if (y1 > y2) { + int tmp = y1; + y1 = y2; + y2 = tmp; + } +#if 0 + // vert line + p = getXYData(s, x1,y1); + for (i = y1; i < y2; ++i) { + *p = color; + p = p + s->lineBytes; + } +#else + for (i = y1; i < y2; ++i) + putcolor2fb(s, x1, i, color); +#endif + } +} + +void mv_drawRect(int no, const mv_Rect *rect, unsigned int color) +{ + mv_drawLine(no, rect->left, rect->top, rect->right, rect->top, color); + mv_drawLine(no, rect->left, rect->bottom, rect->right, rect->bottom, color); + + mv_drawLine(no, rect->left, rect->top, rect->left, rect->bottom, color); + mv_drawLine(no, rect->right, rect->top, rect->right, rect->bottom, color); +} + +void mv_fillRect(int no, const mv_Rect *rect, unsigned char r, unsigned char g, unsigned char b) +{ + int y; + unsigned int color = 0; + + color = rgb2color(r, g, b); + for (y = rect->top; y < rect->bottom ; y++) + mv_drawLine(no, rect->left, y, rect->right, y, color); +} + +int mv_le_to_cpu(char *buf, int size) +{ + int i; + int val = 0; + + for(i = size - 1; i >= 0; i--) { + val = val << 8; + val |= buf[i]; + } + return val; +} + +int mv_loadBmp(int no, unsigned char *fileBuffer, int clearFB) +{ + unsigned char r, g, b; + int i, j, bytes; + int width, height, offset; + short colorBits; + unsigned char *colorMap; + mv_surface img; + bmp_header_t *header; + unsigned int dcolor = 0; + int xpos, ypos; + char *ptr; + int bits_per_pixel; + mv_surface *s; + + char *source, *dst, *tmp_source, *tmp_dst; + int double_width, ali; + + // for 32bits to 16bits + int bundle24, phase1, tmp_offset, tmp_phase1, tmp_bundle24, show_width, over_width, over_high; + + s = &s_surface[no]; + if(s->startAddr == 0) + return 0; + + if (*fileBuffer != 'B') { + printf("fileBuffer : 0x%x = 0x%x \n", fileBuffer, *fileBuffer); + printf("Error : Not BMP Format\r\n"); + return -1; + } + + header = (bmp_header_t *)fileBuffer; + offset = mv_le_to_cpu((char *)&header->data_offset, 4); + width = mv_le_to_cpu((char *)&header->width, 4); + height = mv_le_to_cpu((char *)&header->height, 4); + colorBits = mv_le_to_cpu((char *)&header->bit_count, 2); + + colorMap = (unsigned char *)(fileBuffer + 54); //ÑÕÉ«±íµØÖ·(8bitʱʹÓÃ) + + show_width = width; + over_width = 0; + over_high = 0; + + img.width = width; + img.height = height; + img.lineBytes = s->lineBytes; + + i = 0; + j = 0; + + if(g_display_direction == 0 || g_display_direction == 2) { // the screen is portrait + if (width != s->height) { + if (width > s->height) { + printf("Warning : BMP Width(%d) > LCD(%d)\r\n", width, s->height); + if(g_logo_scale == LOGO_NOT_SCALE) { + /* only surport 24bit or 32bit bmp exceed screen size */ + if(colorBits == 24 || colorBits == 32) { + /* only show bmp center if bmp size exceed screen size*/ + over_width = width - s->height; + width = s->height; + img.width = width; + } + } + } + else + i = (s->height - width) / 2; + } + if (height != s->width) { + if (height > s->width) { + printf("Warning : BMP Height(%d) > LCD(%d)\r\n", height, s->width); + if(g_logo_scale == LOGO_NOT_SCALE) { + if(colorBits == 24 || colorBits == 32) { + over_high = height - s->width; + height = s->width; + img.height = height; + } + } + } + else + j = (s->width - height) / 2; + } + + if ((g_logo_x >= 0) && (g_logo_x < s->height)) i = g_logo_x; + if ((g_logo_y >= 0) && (g_logo_y < s->width)) j = g_logo_y; + + } else { // the screen is landscape + if (width != s->width) { + if (width > s->width) { + printf("Warning : BMP Width(%d) > LCD(%d)\r\n", width, s->width); + if(g_logo_scale == LOGO_NOT_SCALE) { + if(colorBits == 24 || colorBits == 32) { + over_width = width - s->width; + width = s->width; + img.width = width; + } + } + } + else + i = (s->width - width) / 2; + } + if (height != s->height) { + if (height > s->height) { + printf("Warning : BMP Height(%d) > LCD(%d)\r\n", height, s->height); + if(g_logo_scale == LOGO_NOT_SCALE) { + if(colorBits == 24 || colorBits == 32) { + over_high = height - s->height; + height = s->height; + img.height = height; + } + } + } + else + j = (s->height - height) / 2; + } + + if ((g_logo_x >= 0) && (g_logo_x < s->width)) i = g_logo_x; + if ((g_logo_y >= 0) && (g_logo_y < s->height)) j = g_logo_y; + } + + img.startAddr = (s->startAddr + (i * (s->bits_per_pixel >> 3)) + (s->lineBytes * j)); + + /* add for logo scale */ + //set wimg.startAddr = (char *)vpp_calc_align((int)img.startAddr, 64); + + if(g_logo_scale != LOGO_NOT_SCALE) { + if (g_logo_scale == LOGO_MODE_MAX) + g_logo_scale = ((width == 1280 && height == 720) || (width > 1280 || height > 720)) ? + LOGO_ORI_SCALE_FULL : LOGO_720P_SCALE_FULL; + + if(g_logo_scale == LOGO_720P_SCALE_FULL) { + + s->img_width = 1280; + s->img_height = 720; + s->img_startAddr = s->startAddr; + + i = (1280 - width) / 2; + j = (720 - height) / 2; + + img.startAddr = (s->startAddr + (i * (s->bits_per_pixel >> 3)) + (s->lineBytes * j)); + img.startAddr = (char *)vpp_calc_align((int)img.startAddr, 64); + arm_memset(s->startAddr, 0, 720 * s->lineBytes); //clean fb + } else { + s->img_width = width; + s->img_height = height; + s->img_startAddr = img.startAddr; + } + } + /* end of logo scale */ + + xpos = i; + ypos = j; + + if(clearFB) + arm_memset(s->startAddr, 0, s->height * s->lineBytes); //clear fb + + switch (colorBits) { + // AimarMa -- Add 32bit BMP support + case 32: // r,g,b,a + bits_per_pixel = s->bits_per_pixel; + if (bits_per_pixel != 16 && g_display_direction == 1) { + for (i = 0; i <= height - 1 ; i++) { + //source = (char *)(fileBuffer + offset + i * width * 4); + source = (char *)(fileBuffer + offset + i * show_width * 4 + (over_high/2)*show_width * 4 + (over_width/2) * 4); + dst = (char *)(img.startAddr + img.lineBytes * (height - 1 - i)); + mem_cpy_alignment (dst, source, width * 4); + } + } else { + offset = offset + (over_high/2)*show_width * 4 + (over_width/2) * 4; + for (i = height - 1; i >= 0; i--) { + for (j = 0; j < width; j++) { + b = *(fileBuffer + offset); + g = *(fileBuffer + offset + 1); + r = *(fileBuffer + offset + 2); + //a = *(unsigned char*)(fileBuffer + offset + 3); + //*getXYData(&img, j, i) = mv_RGB2Color(r,g,b); + dcolor = rgb2color(r, g, b); + //putcolor2fb(&img, j, i, dcolor); + putcolor2mem(&s_surface[no], j + xpos, i + ypos, dcolor); + offset += 4; + } + offset += over_width * 4; + } + mem2fb(s, width, height, xpos, ypos); + } + break; + + case 24: // r,g,b + if(g_display_direction == 1) { + bits_per_pixel = s->bits_per_pixel; + ptr = malloc(width * 3); + if (!ptr) { + printf("allocate fail!!\n"); + return 0; + } + bytes = 4 - (show_width * 3) % 4; + if (bytes == 4) + bytes = 0; + + // 24bits -> 16bits + bundle24 = (width * 3) % 24; // 8 bits + phase1 = width * 3 - bundle24; // 24 bits + for (i = 0; i <= height - 1 ; i++) { + source = (char *)(fileBuffer + offset + i*show_width * 3 + (over_high/2)*show_width * 3 + (over_width/2) * 3); + dst = (char *)(img.startAddr + img.lineBytes * (height - 1 - i)); + tmp_source = source; + tmp_dst = dst; + tmp_phase1 = phase1; + tmp_bundle24 = bundle24; + ali = 0; + + // dst not ali + if ((int)dst % 4 != 0) { + b = *(source); + g = *(source + 1); + r = *(source + 2); + dcolor = rgb2color(r, g, b); + *(unsigned short *)(dst) = (unsigned short)dcolor; + tmp_dst = dst + 2; + + tmp_source = source + 3; + tmp_phase1 = phase1 - 3; + tmp_bundle24 = tmp_phase1 % 24; + tmp_phase1 = tmp_phase1 - tmp_bundle24; + ali = 1; + } + + // src -> tmp_buffer + mem_cpy_alignment(ptr, tmp_source, (width - ali) * 3); + if (bits_per_pixel == 16) + bit24_to_bit16_ali24 (tmp_dst, ptr, tmp_phase1); + else + bit24_to_bit16_ali32 (tmp_dst, ptr, tmp_phase1); + + if (tmp_bundle24) { + tmp_offset = 0; + source = (char *)(ptr + tmp_phase1); + for (j = 0; j < tmp_bundle24 / 3; j++) { + b = *(source + tmp_offset); + g = *(source + tmp_offset + 1); + r = *(source + tmp_offset + 2); + dcolor = rgb2color(r, g, b); + if (bits_per_pixel == 16) { + tmp_dst = dst + (tmp_phase1 / 3) * 2 + j * 2; + *(unsigned short *)(tmp_dst) = (unsigned short)dcolor; + } else { + tmp_dst = dst + (tmp_phase1 / 3) * 4 + j * 4; + *(unsigned int *)(tmp_dst) = (unsigned int)dcolor; + } + tmp_offset += 3; + } + } + offset += bytes; + } + + if( NULL != ptr ) + free(ptr); + } else { + bytes = 4 - (show_width * 3) % 4; + if (bytes == 4) + bytes = 0; + + offset = offset + (over_high/2)*show_width * 3 + (over_width/2) * 3; + + for (i = height - 1; i >= 0; i--) { + for (j = 0; j < width; j++) { + b = *(fileBuffer + offset); + g = *(fileBuffer + offset + 1); + r = *(fileBuffer + offset + 2); + //*getXYData(&img, j, i) = mv_RGB2Color(r,g,b); + dcolor = rgb2color(r, g, b); + //putcolor2fb(&img, j, i, dcolor); + putcolor2mem(s, j + xpos, i + ypos, dcolor); + offset += 3; + } + offset += bytes; + offset += over_width * 3; + } + mem2fb(s, width, height, xpos, ypos); + } + break; + case 16: { //16bit 555 + double_width = width * 2; + bytes = 4 - width % 4; + if (bytes == 4) + bytes = 0; + if (bitsPerPixel == 16) { + for (i = 0; i <= height - 1 ; i++) { + // multicopy----------------------------------------------- + source = (char *)(fileBuffer + offset + i * double_width); + dst = (char *)(img.startAddr + img.lineBytes * (height - 1 - i)); + mem_cpy_alignment (dst, source, double_width); + //-------------------------------------------------------- + } + } else { + unsigned short color16; + bytes = 4 - (width * 2) % 4; + if (bytes == 4) + bytes = 0; + for (i = height - 1; i >= 0; i--) { + for (j = 0; j < width; j++) { + color16 = *(unsigned short *)(fileBuffer + offset); +#if ( GUI_RGB_FORMAT == RGB_FORMAT_565) + //*getXYData(&img, j, i) = (color16<<1) & 0xFFC0 | (color16 & 0x1F); + dcolor = (unsigned int)((((color16 & 0xF800) << 8) & 0x00FF0000) | (((color16 & 0x7E0) << 5) & 0x0000FF00) | (((color16 & 0x1F) << 3) & 0x000000FF)); + //putcolor2fb(&img, j, i, dcolor); + putcolor2mem(&s_surface[no], j + xpos, i + ypos, dcolor); +#else + //*getXYData(&img, j, i) = mv_RGB2Color((color16 & 0x7C00) >> 7, (color16 & 0x03E0) >> 2, (color16 & 0x001F) << 3); + dcolor = rgb2color((color16 & 0x7C00) >> 7, (color16 & 0x03E0) >> 2, (color16 & 0x001F) << 3); + //putcolor2fb(&img, j, i, dcolor); + putcolor2mem(&s_surface[no], j + xpos, i + ypos, dcolor); +#endif + offset += 2; + } + offset += bytes; + } + mem2fb(s, width, height, xpos, ypos); + } + } + break; + case 8: //256 colormap + bytes = 4 - width % 4; + if (bytes == 4) + bytes = 0; + for (i = height - 1; i >= 0; i--) { + for (j = 0; j < width; j++) { + int offSet = *(fileBuffer + offset) * 4; + b = colorMap[offSet]; + g = colorMap[offSet + 1]; + r = colorMap[offSet + 2]; + //*getXYData(&img, j, i) = mv_RGB2Color(r,g,b); + dcolor = rgb2color(r, g, b); + //putcolor2fb(&img, j, i, dcolor); + putcolor2mem(&s_surface[no], j + xpos, i + ypos, dcolor); + offset ++; + } + offset += bytes; + } + mem2fb(s, width, height, xpos, ypos); + break; + default: + break; + } + + return 0; +} + +static void get_display_postion(const mv_surface *s, int disp_width, int disp_height, int *p_x, int *p_y) +{ + int pos_x = 0, pos_y = 0; + + if(g_display_direction == 0 || g_display_direction == 2) { + if (disp_width > s->height) + printf("Warning : disp_width(%d) > LCD(%d)\r\n", disp_width, s->height); + else + pos_x = (s->height - disp_width) / 2; + + if (disp_height > s->width) + printf("Warning : disp_height(%d) > LCD(%d)\r\n", disp_height, s->width); + else + pos_y = (s->width - disp_height) / 2; + + } else { + if (disp_width > s->width) + printf("Warning : disp_width(%d) > LCD(%d)\r\n", disp_width, s->width); + else + pos_x = (s->width - disp_width) / 2; + + if (disp_height > s->height) + printf("Warning : disp_height(%d) > LCD(%d)\r\n", disp_height, s->height); + else + pos_y = (s->height - disp_height) / 2; + } + + *p_x = pos_x; + *p_y = pos_y; +} + +int init_charge_percent(void) +{ + char *s; + + s = getenv("wmt.ui.uboot.charging_percent"); + if(s && !strcmp(s, "1")) + s_display_percent = 1; + else + s_display_percent = 0; + + s_percent_val = -1; + + return 0; +} + +int clear_charge_percent(unsigned char *fileBuffer) +{ + int blank_width, anim_height; + mv_Rect rect; + int pos_x, pos_y; + bmp_header_t *header; + unsigned int logo_size; + int no; + mv_surface *s; + + if(s_display_percent == 0) + return -1; + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = &s_surface[no]; + if(s->startAddr == 0) + continue; + + if (*fileBuffer != 'B') { + //printf("Error : logo is Not BMP Format. Couldn't clear charging percent\n"); + //return -1; + anim_height = 168; + } else { + if(!g_tf_boot) { + logo_size = (*(unsigned short *)(fileBuffer + 4) << 16) + (*(unsigned short *)(fileBuffer + 2)); + + fileBuffer = fileBuffer + logo_size; + + if (*fileBuffer != 'B') { + //printf("Error : charge-anim is Not BMP Format. Couldn't clear charging percent\n"); + //return -1; + anim_height = 168; + } else { + header = (bmp_header_t *)fileBuffer; + anim_height = mv_le_to_cpu((char *)&header->height, 4); + anim_height = anim_height / CHARGEANIM_PIC_NUM; + } + } else { + header = (bmp_header_t *)fileBuffer; + anim_height = mv_le_to_cpu((char *)&header->height, 4); + anim_height = anim_height / CHARGEANIM_PIC_NUM; + } + } + + blank_width = 4 * CHAR_WIDTH; // clear 4 char + + get_display_postion(s, blank_width, anim_height, &pos_x, &pos_y); + + pos_y = pos_y - CHAR_HEIGHT - CHAR_HEIGHT; + if(pos_y < 0) + pos_y = 0; + + rect.left = pos_x; + rect.right = pos_x + blank_width; + rect.top = pos_y; + rect.bottom = pos_y + CHAR_HEIGHT; + + mv_fillRect(no, &rect, 0, 0, 0); + } + + return 0; +} + +int display_charge_percent(unsigned char *fileBuffer, int percent) +{ + int ret, len; + int text_width, anim_height; + char tmpbuf[20]; + unsigned int rgb = 0xFF00; //green + char r, g, b; + int pos_x, pos_y; + bmp_header_t *header; + unsigned int logo_size; + int no; + mv_surface *s; + + if(s_display_percent == 0) + return -1; + + if(percent < 0 || percent > 100) + return -1; + + if(percent != s_percent_val) { + ret = clear_charge_percent(fileBuffer); + if(ret) + return ret; + + s_percent_val = percent; + } else + return 0; + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = &s_surface[no]; + if(s->startAddr == 0) + continue; + + if (*fileBuffer != 'B') { + //printf("Error : logo is Not BMP Format. Couldn't display charging percent\n"); + //return -1; + anim_height = 168; + } else { + if(!g_tf_boot) { + logo_size = (*(unsigned short *)(fileBuffer + 4) << 16) + (*(unsigned short *)(fileBuffer + 2)); + + fileBuffer = fileBuffer + logo_size; + + if (*fileBuffer != 'B') { + //printf("Error : charge-anim is Not BMP Format. Couldn't display charging percent\n"); + //return -1; + anim_height = 168; + } else { + header = (bmp_header_t *)fileBuffer; + anim_height = mv_le_to_cpu((char *)&header->height, 4); + anim_height = anim_height / CHARGEANIM_PIC_NUM; + } + } else { + header = (bmp_header_t *)fileBuffer; + anim_height = mv_le_to_cpu((char *)&header->height, 4); + anim_height = anim_height / CHARGEANIM_PIC_NUM; + } + } + + len = sprintf(tmpbuf, "%d%%", percent); + tmpbuf[len] = '\0'; + text_width = len * CHAR_WIDTH; + + get_display_postion(s, text_width, anim_height, &pos_x, &pos_y); + + pos_y = pos_y - CHAR_HEIGHT - CHAR_HEIGHT; + if(pos_y < 0) + pos_y = 0; + + r = (rgb >> 16) & 0xFF; + g = (rgb >> 8) & 0xFF; + b = rgb & 0xFF; + + mv_textOut(no, pos_x, pos_y, tmpbuf, r, g, b); + } + + return 0; +} + +static void hint_text(char *p_text, unsigned int rgb) +{ + int xpos, ypos; + int len, text_width, text_height; + mv_Rect rect; + char r, g, b; + int no; + mv_surface *s; + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = &s_surface[no]; + if(s->startAddr == 0) + continue; + + len = strlen(p_text); + + text_width = len * CHAR_WIDTH; + text_height = CHAR_HEIGHT; + + get_display_postion(s, text_width, text_height, &xpos, &ypos); + + rect.left = xpos; + rect.right = xpos + text_width; + rect.top = ypos; + rect.bottom = ypos + CHAR_HEIGHT; + mv_fillRect(no, &rect, 0, 0, 0); + + r = (rgb >> 16) & 0xFF; + g = (rgb >> 8) & 0xFF; + b = rgb & 0xFF; + + mv_textOut(no, xpos, ypos, p_text, r, g, b); + } +} + +void show_text_to_screen(char *p_text, unsigned int rgb) +{ + if(!(g_display_vaild & DISPLAY_ENABLE)) { + if(display_init(0, 0) == -1) { + printf("Display init fail. Don't show_text_to_screen\n"); + return; + } + } + + mv_clearFB(); + + hint_text(p_text, rgb); + + if (g_display_param.vout == VPP_VOUT_LCD) + lcd_blt_enable(g_pwm_setting.pwm_no, 1); + +} + +void show_text_to_screen_no_backlight(char *p_text, unsigned int rgb) +{ + if(!(g_display_vaild & DISPLAY_ENABLE)) + return; + + mv_clearFB(); + + hint_text(p_text, rgb); +} + +static void hint_2lines_text(char *p_text1, char *p_text2, unsigned int rgb) +{ + int xpos, ypos; + int len, text_width, text_height; + mv_Rect rect; + char r, g, b; + int no; + mv_surface *s; + + for(no = 0; no < 2; no++) { + s = &s_surface[no]; + if(s->startAddr == 0) + continue; + + if(strlen(p_text1) >= strlen(p_text2)) + len = strlen(p_text1); + else + len = strlen(p_text2); + + text_width = len * CHAR_WIDTH; + text_height = 2 * CHAR_HEIGHT + 10; + + get_display_postion(s, text_width, text_height, &xpos, &ypos); + + rect.left = xpos; + rect.right = xpos + text_width; + rect.top = ypos; + rect.bottom = ypos + text_height; + mv_fillRect(no, &rect, 0, 0, 0); + + r = (rgb >> 16) & 0xFF; + g = (rgb >> 8) & 0xFF; + b = rgb & 0xFF; + + mv_textOut(no, xpos, ypos, p_text1, r, g, b); + mv_textOut(no, xpos, ypos + CHAR_HEIGHT + 10, p_text2, r, g, b); + } +} + +void show_2lines_text_to_screen(char *p_text1, char *p_text2, unsigned int rgb) +{ + if(!(g_display_vaild & DISPLAY_ENABLE)) { + if(display_init(0, 0) == -1) { + printf("Display init fail. Don't show_text_to_screen\n"); + return; + } + } + + mv_clearFB(); + + hint_2lines_text(p_text1, p_text2, rgb); + + if (g_display_param.vout == VPP_VOUT_LCD) + lcd_blt_enable(g_pwm_setting.pwm_no, 1); + +} + +void show_2lines_text_to_screen_no_backlight(char *p_text1, char *p_text2, unsigned int rgb) +{ + if(!(g_display_vaild & DISPLAY_ENABLE)) + return; + + mv_clearFB(); + + hint_2lines_text(p_text1, p_text2, rgb); +} + +int show_charge_picture(unsigned char *fileBuffer, int picture_no) +{ + int i, j, bytes; + unsigned char r, g, b; + bmp_header_t *header; + int width, height, offset; + short colorBits; + //mv_surface img; + unsigned int dcolor = 0; + int xpos, ypos; + unsigned int logo_size; + int no; + mv_surface *s; + unsigned char *buffer; + + if(!g_tf_boot) { + if (*fileBuffer != 'B') { + printf("Error : logo is Not BMP Format\n"); + if(picture_no == CHARGEANIM_PIC_NUM - 1) + hint_text("Low Battery", 0xFFFF00); + else + hint_text("Charging now ...", 0xFF00); + return -1; + } + + logo_size = (*(unsigned short *)(fileBuffer + 4) << 16) + (*(unsigned short *)(fileBuffer + 2)); + + fileBuffer = fileBuffer + logo_size; + + if (*fileBuffer != 'B') { + printf("Error : charge-anim is Not BMP Format\n"); + if(picture_no == CHARGEANIM_PIC_NUM - 1) + hint_text("Low Battery", 0xFFFF00); + else + hint_text("Charging now ...", 0xFF00); + + return -1; + } + } else { + if (*fileBuffer != 'B') { + printf("Error : charge-anim is Not BMP Format\n"); + if(picture_no == CHARGEANIM_PIC_NUM - 1) + hint_text("Low Battery", 0xFFFF00); + else + hint_text("Charging now ...", 0xFF00); + + return -1; + } + } + + if(picture_no < 0 || picture_no >= CHARGEANIM_PIC_NUM) { + printf("Error : picture no (%d) error\n", picture_no); + return -1; + } + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = &s_surface[no]; + if(s->startAddr == 0) + continue; + + buffer = fileBuffer; + + header = (bmp_header_t *)buffer; + colorBits = mv_le_to_cpu((char *)&header->bit_count, 2); + if(colorBits != 24) { + printf("Error : charge_animation colorBits = %d, current only support 24bits\n", + colorBits); + return -1; + } + + offset = mv_le_to_cpu((char *)&header->data_offset, 4); + width = mv_le_to_cpu((char *)&header->width, 4); + height = mv_le_to_cpu((char *)&header->height, 4); + + height = height / CHARGEANIM_PIC_NUM; + + get_display_postion(s, width, height, &xpos, &ypos); + + buffer += (width * height * 3) * (6 - picture_no); + + switch (colorBits) { + case 24: // r,g,b + bytes = 4 - (width * 3) % 4; + if (bytes == 4) + bytes = 0; + for (i = height - 1; i >= 0; i--) { + for (j = 0; j < width; j++) { + b = *(buffer + offset); + g = *(buffer + offset + 1); + r = *(buffer + offset + 2); + dcolor = rgb2color(r, g, b); + + putcolor2mem(s, j + xpos, i + ypos, dcolor); + offset += 3; + } + offset += bytes; + } + + mem2fb(s, width, height, xpos, ypos); + break; + } + } + + return 0; +} + +static int getGlyphIndex(unsigned short unicode) +{ + int i; + GlyphRange *const range = (GlyphRange *)(m_fh + 1); + GlyphScatter *start; + GlyphScatter *scatter; + int low; + int high; + int mid; + int glyphIndex = 1; // == 1 to skip missing lattice + + for (i = 0 ; i < m_fh->rangeCount; i++) { + if ( unicode >= range[i].ucs2Start && unicode <= range[i].ucs2End) { + glyphIndex += (unicode - range[i].ucs2Start); + return glyphIndex; + } + glyphIndex += range[i].ucs2End - range[i].ucs2Start + 1; + } + + start = (GlyphScatter *)(range + m_fh->rangeCount); + low = 0; + high = m_fh->scatterCount - 1; + + while (low <= high) { + mid = (low + high) / 2; + scatter = start + mid; + if ( *scatter < unicode) + low = mid + 1; + else if ( *scatter > unicode) + high = mid - 1; + else + return(glyphIndex + mid); + } + return 0; // the missing glyph +} + + +static unsigned char *getLattice(int glyphIndex) +{ + return m_glyphStart + glyphIndex * m_fh->glyphBytes; +} + +static int setFontFileDat(const unsigned char *dat) +{ + FontFileHeadV1 *fh = (FontFileHeadV1 *)dat; + if ( fh->magic[0] != 'F' || fh->magic[1] != 'T') { + return -1; + } + + m_fileStart = (unsigned char * )dat; + m_fh = (FontFileHeadV1 *)m_fileStart; + + m_glyphStart = m_fileStart + sizeof(FontFileHeadV1) + + m_fh->rangeCount * sizeof(GlyphRange) + + m_fh->scatterCount * sizeof(GlyphScatter); + return 0; +} + +static void loadFontImage(int code, mv_surface *img) +{ + int idx = getGlyphIndex((unsigned short)code); + + img->width = m_fh->charWidth; + img->height = m_fh->charHeight; + img->startAddr = (char *)getLattice(idx); +} + +void mv_textOut(int no, int x, int y, const char *string, unsigned char r, unsigned char g, unsigned char b) +{ + mv_surface img; + const char *p; + const unsigned char *lattice; + int h, w; + unsigned int textColor = 0; + const mv_surface *s = &s_surface[no]; + + for (p = string; *p != '\0'; p++) { + loadFontImage(*p, &img); + lattice = (const unsigned char * )img.startAddr; + if (!lattice) + continue; + + for ( h = 0 ; h < img.height; ++h) { + unsigned char mask = 0x80; + for ( w = 0 ; w < img.width; ++w) { + if (*lattice & mask) { + //*(getXYData(&s_primary, x + w, y + h)) = textColor; + textColor = rgb2color(r, g, b); + putcolor2fb(s, x + w, y + h, textColor); + } + mask >>= 1; + if ( mask == 0 ) { + mask = 0x80; + ++lattice; // next byte + } + } + if (mask != 0x80) { + ++lattice; // next byte + } + } + + x += img.width; + } +} + +void mem_cpy_alignment(char *des, char *src, int len) +{ + char *copy_some_src, *copy_some_dst; + int dst_alignment = (int)des % 4; + int src_alignment = (int)src % 4; + int i, tmp_len, len_less, len_less_4_byte; + + int phase1, phase2; + + // check dst, src ali + // all ali + if (!dst_alignment && !src_alignment) { + // check len 32bytes ali + phase1 = len_less = len % 32; + // len ali + if(!phase1 && len >= 32) { + mem_copy(src, des, len); + return; + } else { + // trans 32bytes ali data first + tmp_len = len - len_less; + if(len >= 32) + mem_copy(src, des, tmp_len); + // check len_less 4 bytes ali + phase2 = len_less % 4; + if(!phase2 && phase2 >= 4) { + less_mem_copy(src + tmp_len, des + tmp_len, len_less); + return; + } else { + // trans 4bytes ali data first + len_less = len_less - phase2; + if(len_less >= 4) + less_mem_copy(src + tmp_len, des + tmp_len, len_less); + // trans least bytes + for (i = 0; i < phase2; i++) + *(des + tmp_len + len_less + i) = *(src + tmp_len + len_less + i); + return; + } + } + } + tmp_len = len; + // dst not aligment, let dst alignment first + // ==================================================== + copy_some_src = (char *)(src); + copy_some_dst = (char *)(des); + if (dst_alignment != 0) { + for (i = 0; i < 4 - dst_alignment; i++) { + *(des + i) = *(src + i); + + // copy len + tmp_len = tmp_len - 1; + + // copy complete + if (tmp_len <= 0) + return; + } + + // src + bytes of already copy + copy_some_src = (char *)(src + ( 4 - dst_alignment)) ; + copy_some_dst = (char *)(des + ( 4 - dst_alignment)) ; + } + src_alignment = (int)copy_some_src % 4; + + // ==================================================== + // handle data len < 32bytes + if (tmp_len < 32) { + phase1 = len_less = tmp_len % 4; + // tmp_len 4bytes ali + if (!phase1 && tmp_len >= 4) { + switch (src_alignment) { + case 1: + byte1_less_bundle_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + + case 2: + byte2_less_bundle_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + + case 3: + byte3_less_bundle_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + + default: + less_mem_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + } + return; + } else { + // trans 4bytes ali data first + len_less = tmp_len - phase1; + if(len_less >= 4) + switch (src_alignment) { + case 1: + byte1_less_bundle_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + + case 2: + byte2_less_bundle_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + + case 3: + byte3_less_bundle_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + + default: + less_mem_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + } + // trans least bytes + for (i = 0; i < phase1; i++) + *(copy_some_dst + len_less + i) = *(copy_some_src + len_less + i); + return; + } + } + // ==================================================== + phase1 = tmp_len % 32; + // data_len 32bytes ali + if (!phase1) { + switch (src_alignment) { + case 1: + byte1_alig_mem_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + + case 2: + byte2_alig_mem_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + + case 3: + byte3_alig_mem_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + + default: + mem_copy (copy_some_src - src_alignment, copy_some_dst, tmp_len); + break; + } + return; + } else { + len_less = tmp_len - phase1; + // trans 32bytes ali data first + switch (src_alignment) { + case 1: + byte1_alig_mem_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + + case 2: + byte2_alig_mem_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + + case 3: + byte3_alig_mem_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + + default: + mem_copy (copy_some_src - src_alignment, copy_some_dst, len_less); + break; + } + phase2 = phase1 % 4; + len_less_4_byte = phase1 - phase2; + // data_len 4bytes ali + if (!phase2) { + switch (src_alignment) { + case 1: + byte1_less_bundle_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + + case 2: + byte2_less_bundle_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + + case 3: + byte3_less_bundle_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + + default: + less_mem_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + } + return; + } else { + // trans 4bytes ali data first + if(len_less_4_byte >= 4) { + switch (src_alignment) { + case 1: + byte1_less_bundle_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + + case 2: + byte2_less_bundle_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + + case 3: + byte3_less_bundle_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + + default: + less_mem_copy (copy_some_src - src_alignment + len_less, copy_some_dst + len_less, len_less_4_byte); + break; + } + } + + // trans least bytes + for (i = 0; i < phase2; i++) + *(copy_some_dst + len_less + len_less_4_byte + i) = *(copy_some_src + len_less + len_less_4_byte + i); + return; + } + } +} + diff --git a/common/wmt_display/minivgui.h b/common/wmt_display/minivgui.h new file mode 100755 index 0000000..89f124a --- /dev/null +++ b/common/wmt_display/minivgui.h @@ -0,0 +1,116 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +/** + * A mini gui implementation (copied some code from VGUI) + * functions: + * 1. draw line (horz or vert only) + * 2. draw rectangle, fill rectangle, + * 3. draw bitmap ( Windows bmp format) + * 4. draw text ( note, ascii only and the text font was gererated by + * vgui's FontGen 1.0 tool) + * + * Usage: + * first maybe you want to change this line to fit your rgb format + #define mv_RGB_FORMAT mv_RGB_FORMAT_565 + * in the source code firstly you need to prepare all HW related jobs, + * such as turn on panel backlight/init LCDC + * after that the first function you need to invoked is mv_initPrimary. + * You need to set the correct member in mv_surface argument. + * After that you can call all functions + * + * Here is a example: + * + * + mv_surface s; + s.width = 800; + s.height = 480; + s.lineBytes = 800 * 2; + // if the panel is 16bit + s.startAddr = 0x7C000000; + // the frame buffer address + + mv_initPrimary(&s); + + mv_Rect r; + r.left = 0; + r.right = s.width; + r.top = 0; + r.bottom = s.height; + //fill whole screen with red color + mv_fillRect(&r, mv_RGB2Color(255, 0, 0)); + + //draw some text on the screen (build-in font size is 12x24) + mv_textOut(0, 0, "Hello,world!", mv_RGB2Color(0, 0, 0)); + mv_textOut(0, 25, "Hello, mini VGUI!", mv_RGB2Color(0, 0, 0)); + * + */ +#ifndef MINIVGUI_H_INCLUDED +#define MINIVGUI_H_INCLUDED + +#ifdef __cplusplus +extern "C" { +#endif + +#include "wmt_display.h" + +extern int g_display_direction; + +/** + * init minivgui primary screen. this is the first function need be called + */ +void mv_initSurface(int no,const mv_surface * s); +mv_surface *mv_getSurface(int no); +void mv_dumpSurface(void); + +void mv_drawLine(int no, int x1, int y1, int x2, int y2, unsigned int color); +void mv_drawRect(int no, const mv_Rect* rect, unsigned int color); +void mv_fillRect(int no, const mv_Rect* rect, unsigned char r, unsigned char g, unsigned char b); + +void check_display_direction(void); +void mv_clearFB(void); +int show_charge_picture(unsigned char* fileBuffer, int picture_no); + +void check_tf_boot(void); + +/** + * draw text on the screen (Note: only acsii supported) + */ +void mv_textOut(int no, int x, int y, const char * string, unsigned char r, unsigned char g, unsigned char b); +int mv_loadBmp(int no, unsigned char* fileBuffer, int clearFB); +void show_text_to_screen(char *p_text, unsigned int rgb); +void show_text_to_screen_no_backlight(char *p_text, unsigned int rgb); +void show_2lines_text_to_screen(char *p_text1, char *p_text2, unsigned int rgb); +void show_2lines_text_to_screen_no_backlight(char *p_text1, char *p_text2, unsigned int rgb); + +/** +* display charging percent +**/ +int init_charge_percent(void); +int clear_charge_percent(unsigned char* fileBuffer); +int display_charge_percent(unsigned char* fileBuffer, int percent); + +// for mem copy +void mem_cpy_alignment(char *des, char *src, int len); + +#ifdef __cplusplus +} +#endif + +#endif // MINIVGUI_H_INCLUDED + + diff --git a/common/wmt_display/parse-edid.c b/common/wmt_display/parse-edid.c new file mode 100755 index 0000000..8bf8da7 --- /dev/null +++ b/common/wmt_display/parse-edid.c @@ -0,0 +1,1069 @@ +/*++ + * linux/drivers/video/wmt/parse-edid.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define PARSE_EDID_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ + +#include "vpp.h" +#include "edid.h" +#include "hdmi.h" + +const char edid_v1_header[] = { + 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}; + +const char edid_v1_descriptor_flag[] = { 0x00, 0x00 }; + +#define COMBINE_HI_8LO(hi, lo) \ + ((((unsigned)hi) << 8) | (unsigned)lo) + +#define COMBINE_HI_4LO(hi, lo) \ + ((((unsigned)hi) << 4) | (unsigned)lo) + +#define UPPER_NIBBLE(x) \ + (((128|64|32|16) & (x)) >> 4) + +#define LOWER_NIBBLE(x) \ + ((1|2|4|8) & (x)) + +#define MONITOR_NAME 0xfc +#define MONITOR_LIMITS 0xfd +#define UNKNOWN_DESCRIPTOR -1 +#define DETAILED_TIMING_BLOCK -2 + +struct edid_timing_t edid_establish_timing[] = { + { 800, 600, 60 }, { 800, 600, 56 }, { 640, 480, 75 }, { 640, 480, 72 }, + { 640, 480, 67 }, { 640, 480, 60 }, { 720, 400, 88 }, { 720, 400, 70 }, + { 1280, 1024, 75 }, { 1024, 768, 75 }, { 1024, 768, 70 }, + { 1024, 768, 60 }, { 1024, 768, 87 }, { 832, 624, 75 }, + { 800, 600, 75 }, { 800, 600, 72 }, { 1152, 870, 75 } +}; +int edid_msg_enable; +int edid_disable; +struct edid_parsed_t edid_parsed; + +#undef DBGMSG +#define DBGMSG(fmt, args...) if (edid_msg_enable) \ + DPRINT(fmt, ## args) + +static int block_type(char *block) +{ + if (!memcmp(edid_v1_descriptor_flag, block, 2)) { + /* descriptor */ + if (block[2] != 0) + return UNKNOWN_DESCRIPTOR; + return block[3]; + } + /* detailed timing block */ + return DETAILED_TIMING_BLOCK; +} /* End of block_type() */ + +static char *get_vendor_sign(char *block, char *sign) +{ + unsigned short h; + + /* + 08h WORD big-endian manufacturer ID (see #00136) + bits 14-10: first letter (01h='A', 02h='B', etc.) + bits 9-5: second letter + bits 4-0: third letter + */ + h = COMBINE_HI_8LO(block[0], block[1]); + sign[0] = ((h >> 10) & 0x1f) + 'A' - 1; + sign[1] = ((h >> 5) & 0x1f) + 'A' - 1; + sign[2] = (h & 0x1f) + 'A' - 1; + sign[3] = 0; + return sign; +} /* End of get_vendor_sign() */ + +static char *get_monitor_name(char *block, char *name) +{ +#define DESCRIPTOR_DATA 5 + + char *ptr = block + DESCRIPTOR_DATA; + unsigned i; + + for (i = 0; i < 13; i++, ptr++) { + if (*ptr == 0xa) { + name[i] = 0; + return name; + } + name[i] = *ptr; + } + return name; +} /* End of get_monitor_name() */ + +static int parse_timing_description(char *dtd, struct edid_info_t *info) +{ +#define PIXEL_CLOCK_LO ((unsigned)dtd[0]) +#define PIXEL_CLOCK_HI ((unsigned)dtd[1]) +#define PIXEL_CLOCK (COMBINE_HI_8LO(PIXEL_CLOCK_HI, PIXEL_CLOCK_LO) * 10000) +#define H_ACTIVE_LO ((unsigned)dtd[2]) +#define H_BLANKING_LO ((unsigned)dtd[3]) +#define H_ACTIVE_HI UPPER_NIBBLE((unsigned)dtd[4]) +#define H_ACTIVE COMBINE_HI_8LO(H_ACTIVE_HI, H_ACTIVE_LO) +#define H_BLANKING_HI LOWER_NIBBLE((unsigned)dtd[4]) +#define H_BLANKING COMBINE_HI_8LO(H_BLANKING_HI, H_BLANKING_LO) +#define V_ACTIVE_LO ((unsigned)dtd[5]) +#define V_BLANKING_LO ((unsigned)dtd[6]) +#define V_ACTIVE_HI UPPER_NIBBLE((unsigned)dtd[7]) +#define V_ACTIVE COMBINE_HI_8LO(V_ACTIVE_HI, V_ACTIVE_LO) +#define V_BLANKING_HI LOWER_NIBBLE((unsigned)dtd[7]) +#define V_BLANKING COMBINE_HI_8LO(V_BLANKING_HI, V_BLANKING_LO) +#define H_SYNC_OFFSET_LO ((unsigned)dtd[8]) +#define H_SYNC_WIDTH_LO ((unsigned)dtd[9]) +#define V_SYNC_OFFSET_LO UPPER_NIBBLE((unsigned)dtd[10]) +#define V_SYNC_WIDTH_LO LOWER_NIBBLE((unsigned)dtd[10]) +#define V_SYNC_WIDTH_HI ((unsigned)dtd[11] & (1|2)) +#define V_SYNC_OFFSET_HI (((unsigned)dtd[11] & (4|8)) >> 2) +#define H_SYNC_WIDTH_HI (((unsigned)dtd[11] & (16|32)) >> 4) +#define H_SYNC_OFFSET_HI (((unsigned)dtd[11] & (64|128)) >> 6) +#define V_SYNC_WIDTH COMBINE_HI_4LO(V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO) +#define V_SYNC_OFFSET COMBINE_HI_4LO(V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO) +#define H_SYNC_WIDTH COMBINE_HI_4LO(H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO) +#define H_SYNC_OFFSET COMBINE_HI_4LO(H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO) +#define H_SIZE_LO ((unsigned)dtd[12]) +#define V_SIZE_LO ((unsigned)dtd[13]) +#define H_SIZE_HI UPPER_NIBBLE((unsigned)dtd[14]) +#define V_SIZE_HI LOWER_NIBBLE((unsigned)dtd[14]) +#define H_SIZE COMBINE_HI_8LO(H_SIZE_HI, H_SIZE_LO) +#define V_SIZE COMBINE_HI_8LO(V_SIZE_HI, V_SIZE_LO) +#define H_BORDER ((unsigned)dtd[15]) +#define V_BORDER ((unsigned)dtd[16]) +#define FLAGS ((unsigned) dtd[17]) +#define INTERLACED (FLAGS & 128) +#define SYNC_TYPE (FLAGS & 3 << 3) /* bits 4,3 */ +#define SYNC_SEPARATE (3 << 3) +#define HSYNC_POSITIVE (FLAGS & 4) +#define VSYNC_POSITIVE (FLAGS & 2) + + int htotal, vtotal; + int i; + struct fb_videomode *t; + int fps; + int vmul; + + htotal = H_ACTIVE + H_BLANKING; + vtotal = V_ACTIVE + V_BLANKING; + + DBGMSG("Detail Timing: \"%dx%d\"\n", H_ACTIVE, V_ACTIVE); + DBGMSG("\tVfreq %dHz, Hfreq %dkHz\n", + PIXEL_CLOCK / (vtotal * htotal), + PIXEL_CLOCK / (htotal * 1000)); + DBGMSG("\tDotClock\t%d\n", PIXEL_CLOCK / 1000000); + DBGMSG("\tHTimings\t%u %u %u %u\n", H_ACTIVE, + H_ACTIVE + H_SYNC_OFFSET, + H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, + htotal); + + DBGMSG("\tVTimings\t%u %u %u %u\n", V_ACTIVE, + V_ACTIVE + V_SYNC_OFFSET, + V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, + vtotal); + + if (INTERLACED || (SYNC_TYPE == SYNC_SEPARATE)) { + DBGMSG("\tFlags\t%s\"%sHSync\" \"%sVSync\"\n", + INTERLACED ? "\"Interlace\" " : "", + HSYNC_POSITIVE ? "+" : "-", + VSYNC_POSITIVE ? "+" : "-"); + } + + for (i = 0; i < 4; i++) { + t = &info->detail_timing[i]; + if (t->pixclock == 0) + break; + } + + if (i >= 4) { + DBGMSG("*W* slot full\n"); + return 0; + } + + t->pixclock = KHZ2PICOS(PIXEL_CLOCK / 1000); + t->right_margin = H_SYNC_OFFSET; + t->hsync_len = H_SYNC_WIDTH; + t->xres = H_ACTIVE; + t->left_margin = H_BLANKING - (H_SYNC_WIDTH + H_SYNC_OFFSET); + t->vmode = INTERLACED ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED; + vmul = (INTERLACED) ? 2 : 1; + t->lower_margin = V_SYNC_OFFSET * vmul; + t->vsync_len = V_SYNC_WIDTH * vmul; + t->yres = V_ACTIVE * vmul; + t->upper_margin = V_BLANKING - (V_SYNC_WIDTH + V_SYNC_OFFSET); + + fps = vpp_calc_refresh(PIXEL_CLOCK, htotal, vtotal); + t->refresh = fps; + t->sync = HSYNC_POSITIVE ? (FB_SYNC_HOR_HIGH_ACT) : 0; + t->sync |= VSYNC_POSITIVE ? (FB_SYNC_VERT_HIGH_ACT) : 0; + + if (vout_check_ratio_16_9(H_ACTIVE, V_ACTIVE)) + info->option |= EDID_OPT_16_9; +#if 0 + DBGMSG("%dx%d,%d,%s\n", H_ACTIVE, V_ACTIVE, t->pixel_clock, + (info->option & EDID_OPT_16_9) ? "16:9" : "4:3"); +#endif + return 0; +} /* End of parse_timing_description() */ + +static int parse_dpms_capabilities(char flags) +{ +#define DPMS_ACTIVE_OFF (1 << 5) +#define DPMS_SUSPEND (1 << 6) +#define DPMS_STANDBY (1 << 7) + + DBGMSG("# DPMS capabilities: Active off:%s Suspend:%s Standby:%s\n\n", + (flags & DPMS_ACTIVE_OFF) ? "yes" : "no", + (flags & DPMS_SUSPEND) ? "yes" : "no", + (flags & DPMS_STANDBY) ? "yes" : "no"); + return 0; +} /* End of parse_dpms_capabilities() */ + +static int parse_monitor_limits(char *block, struct edid_info_t *info) +{ +#define V_MIN_RATE block[5] +#define V_MAX_RATE block[6] +#define H_MIN_RATE block[7] +#define H_MAX_RATE block[8] +#define MAX_PIXEL_CLOCK (((int)block[9]) * 10) +#define GTF_SUPPORT block[10] + + DBGMSG("Monitor limit\n"); + DBGMSG("\tHorizontal Frequency: %u-%u Hz\n", H_MIN_RATE, H_MAX_RATE); + DBGMSG("\tVertical Frequency: %u-%u kHz\n", V_MIN_RATE, V_MAX_RATE); + if (MAX_PIXEL_CLOCK == 10 * 0xff) { + DBGMSG("\tMax dot clock not given\n"); + } else { + DBGMSG("\tMax dot clock (video bandwidth) %u MHz\n", + (int)MAX_PIXEL_CLOCK); + info->pixel_clock_limit = MAX_PIXEL_CLOCK; + } + + if (GTF_SUPPORT) + DBGMSG("\tEDID version 3 GTF given: contact author\n"); + return 0; +} /* End of parse_monitor_limits() */ + +static int get_established_timing(char *edid, struct edid_info_t *info) +{ + char time_1, time_2; + + time_1 = edid[ESTABLISHED_TIMING_I]; + time_2 = edid[ESTABLISHED_TIMING_II]; + info->establish_timing = time_1 + (time_2 << 8); + + /*--------------------------------------------------------------------- + 35: ESTABLISHED TIMING I + bit 7-0: 720x400@70 Hz, 720x400@88 Hz, 640x480@60 Hz, 640x480@67 Hz, + 640x480@72 Hz, 640x480@75 Hz, 800x600@56 Hz, 800x600@60 Hz + ---------------------------------------------------------------------*/ + DBGMSG("Established Timimgs I: 0x%x\n", time_1); + if (time_1 & 0x80) + DBGMSG("\t%dx%d@%dHz\n", 720, 400, 70); + if (time_1 & 0x40) + DBGMSG("\t%dx%d@%dHz\n", 720, 400, 88); + if (time_1 & 0x20) + DBGMSG("\t%dx%d@%dHz\n", 640, 480, 60); + if (time_1 & 0x10) + DBGMSG("\t%dx%d@%dHz\n", 640, 480, 67); + if (time_1 & 0x08) + DBGMSG("\t%dx%d@%dHz\n", 640, 480, 72); + if (time_1 & 0x04) + DBGMSG("\t%dx%d@%dHz\n", 640, 480, 75); + if (time_1 & 0x02) + DBGMSG("\t%dx%d@%dHz\n", 800, 600, 56); + if (time_1 & 0x01) + DBGMSG("\t%dx%d@%dHz\n", 800, 600, 60); + + /*--------------------------------------------------------------------- + 36: ESTABLISHED TIMING II + bit 7-0: 800x600@72 Hz, 800x600@75 Hz, 832x624@75 Hz, + 1024x768@87 Hz (Interlaced), 1024x768@60 Hz, 1024x768@70 Hz, + 1024x768@75 Hz, 1280x1024@75 Hz + ---------------------------------------------------------------------*/ + DBGMSG("Established Timimgs II: 0x%x\n", time_2); + if (time_2 & 0x80) + DBGMSG("\t%dx%d@%dHz\n", 800, 600, 72); + if (time_2 & 0x40) + DBGMSG("\t%dx%d@%dHz\n", 800, 600, 75); + if (time_2 & 0x20) + DBGMSG("\t%dx%d@%dHz\n", 832, 624, 75); + if (time_2 & 0x10) + DBGMSG("\t%dx%d@%dHz (Interlace)\n", 1024, 768, 87); + if (time_2 & 0x08) + DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 60); + if (time_2 & 0x04) + DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 70); + if (time_2 & 0x02) + DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 75); + if (time_2 & 0x01) + DBGMSG("\t%dx%d@%dHz\n", 1280, 1024, 75); + return 0; +} /* End of get_established_timing() */ + +static int get_standard_timing(char *edid, struct edid_info_t *info) +{ + char *ptr = edid + STANDARD_TIMING_IDENTIFICATION_START; + int h_res, v_res, v_freq; + int byte_1, byte_2, aspect, i; + + /*--------------------------------------------------------------------- + First byte + Horizontal resolution. Multiply by 8, then add 248 for actual value. + Second byte + bit 7-6: Aspect ratio. Actual vertical resolution depends on horizontal + resolution. + 00=16:10, 01=4:3, 10=5:4, 11=16:9 (00=1:1 prior to v1.3) + bit 5-0: Vertical frequency. Add 60 to get actual value. + ---------------------------------------------------------------------*/ + DBGMSG("Standard Timing Identification\n"); + for (i = 0; i < STANDARD_TIMING_IDENTIFICATION_SIZE / 2; i++) { + byte_1 = *ptr++; + byte_2 = *ptr++; + if ((byte_1 == 0x01) && (byte_2 == 0x01)) + break; + h_res = (byte_1 * 8) + 248; + aspect = byte_2 & 0xC0; + switch (aspect) { + default: + case 0x00: + v_res = h_res * 10/16; + break; + case 0x40: + v_res = h_res * 3/4; + break; + case 0x80: + v_res = h_res * 4/5; + break; + case 0xC0: + v_res = h_res * 9/16; + break; + } + v_freq = (byte_2 & 0x1F) + 60; + DBGMSG("\t%dx%d@%dHz\n", h_res, v_res, v_freq); + info->standard_timing[i].resx = h_res; + info->standard_timing[i].resy = v_res; + info->standard_timing[i].freq = v_freq; + } + return 0; +} /* End of get_standard_timing() */ + +static int edid_parse_v1(char *edid, struct edid_info_t *info) +{ + char *block; + char *monitor_name = 0; + char monitor_alt_name[100]; + char vendor_sign[4]; + int i, ret = 0; + + if (edid_checksum(edid, EDID_LENGTH)) { + DBG_ERR("checksum failed\n"); + ret = -1; + goto parse_end; + } + + if (memcmp(edid+EDID_HEADER, edid_v1_header, EDID_HEADER_END+1)) { + DBGMSG("*E* first bytes don't match EDID version 1 header\n"); + ret = -1; + goto parse_end; + } + + if(edid_msg_enable) + edid_dump(edid); + + DBGMSG("[EDID] EDID version: %d.%d\n", + (int)edid[EDID_STRUCT_VERSION], + (int)edid[EDID_STRUCT_REVISION]); + + get_vendor_sign(edid + ID_MANUFACTURER_NAME, (char *) &vendor_sign); + + info->width = edid[EDID_MAX_HOR_IMAGE_SIZE] * 10; + info->height = edid[EDID_MAX_VER_IMAGE_SIZE] * 10; + DBGMSG("[EDID] max hor %d cm ver %d cm\n", info->width, info->height); + + /*--------------------------------------------------------------------- + Parse Monitor name + ---------------------------------------------------------------------*/ + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, + block += DETAILED_TIMING_DESCRIPTION_SIZE) { + if (block_type(block) == MONITOR_NAME) { + monitor_name = + get_monitor_name(block, monitor_alt_name); + break; + } + } + + if (!monitor_name) { + /* Stupid djgpp hasn't snDBGMSG so we have to + hack something together */ + if (strlen(vendor_sign) + 10 > sizeof(monitor_alt_name)) + vendor_sign[3] = 0; + + sprintf(monitor_alt_name, "%s:%02x%02x", + vendor_sign, edid[ID_MODEL], edid[ID_MODEL+1]); + monitor_name = monitor_alt_name; + } + + DBGMSG("Identifier \"%s\"\n", monitor_name); + DBGMSG("VendorName \"%s\"\n", vendor_sign); + DBGMSG("ModelName \"%s\"\n", monitor_name); + + memset(edid_parsed.tv_name.vendor_name, 0, sizeof(edid_parsed.tv_name.vendor_name)); + strcpy(edid_parsed.tv_name.vendor_name, vendor_sign); + + memset(edid_parsed.tv_name.monitor_name, 0, sizeof(edid_parsed.tv_name.monitor_name)); + if (strlen(monitor_name) < MONITOR_NAME_LEN) + strcpy(edid_parsed.tv_name.monitor_name, monitor_name); + else + strncpy(edid_parsed.tv_name.monitor_name, monitor_name, MONITOR_NAME_LEN - 1); + + parse_dpms_capabilities(edid[DPMS_FLAGS]); + + /*--------------------------------------------------------------------- + Parse ESTABLISHED TIMING I and II + ---------------------------------------------------------------------*/ + get_established_timing(edid, info); + + /*--------------------------------------------------------------------- + Parse STANDARD TIMING IDENTIFICATION + ---------------------------------------------------------------------*/ + get_standard_timing(edid, info); + + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, + block += DETAILED_TIMING_DESCRIPTION_SIZE) { + if (block_type(block) == MONITOR_LIMITS) + parse_monitor_limits(block, info); + } + + block = edid + DETAILED_TIMING_DESCRIPTIONS_START; + for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++, + block += DETAILED_TIMING_DESCRIPTION_SIZE) { + if (block_type(block) == DETAILED_TIMING_BLOCK) + parse_timing_description(block, info); + } +parse_end: + return ret; +} + +void edid_parse_CEA_VendorSpecDataBlock(char *block, int len, + struct edid_info_t *info) +{ + int index; + char temp; + + DBGMSG("Vendor Spec Data Block\n"); + if (len < 5) /* min size */ + return; + /* IEEE Registration Identifier 0x000C03 */ + if ((block[1] == 0x03) && (block[2] == 0x0C) && + (block[3] == 0x0)) { + info->option |= EDID_OPT_HDMI; + DBGMSG("\t support HDMI\n"); + } + DBGMSG("\t Source Physical Addr %d.%d.%d.%d\n", + (block[4] & 0xF0) >> 4, block[4] & 0x0F, + (block[5] & 0xF0) >> 4, block[5] & 0x0F); + info->hdmi_phy_addr = (block[4] << 8) + block[5]; + + /* extersion fields */ + if (len < 8) + return; + DBGMSG("\t%s support AI\n", + (block[6] & 0x80) ? "" : "no"); + DBGMSG("\t%s support 30 bits/pixel(10 bits/color)\n", + (block[6] & 0x40) ? "" : "no"); + DBGMSG("\t%s support 36 bits/pixel(12 bits/color)\n", + (block[6] & 0x20) ? "" : "no"); + DBGMSG("\t%s support 48 bits/pixel(16 bits/color)\n", + (block[6] & 0x10) ? "" : "no"); + DBGMSG("\t%s support YUV444 in Deep Color mode\n", + (block[6] & 0x08) ? "" : "no"); + DBGMSG("\t%s support DVI dual-link\n", + (block[6] & 0x01) ? "" : "no"); + DBGMSG("\tMax TMDS Clock %d MHz\n", block[7] * 5); + temp = block[8]; + index = 9; + + if (temp & BIT(7)) { + DBGMSG("\tVideo Latency %d,Audio Latency %d\n", + block[index], block[index+1]); + index += 2; + } + + if (temp & BIT(6)) { + DBGMSG("\tInterlaced Video Latency %d,Audio Latency %d\n", + block[index], block[index+1]); + index += 2; + } + + if (temp & BIT(5)) { + int hdmi_xx_len, hdmi_3d_len; + + DBGMSG("\tHDMI Video present\n"); + temp = block[index]; + if (temp & 0x80) + DBGMSG("\t\t3D present support Mandatory formats\n"); + if (temp & 0x60) + DBGMSG("\t\t3D Multi present %d\n", (temp & 0x60) >> 5); + DBGMSG("\t\tImage size %d\n", (temp & 0x18) >> 3); + hdmi_xx_len = (block[index + 1] & 0xE0) >> 5; + hdmi_3d_len = block[index + 1] & 0x1F; + DBGMSG("\t\thdmi_xx_len %d,hdmi_3d_len %d\n", + hdmi_xx_len, hdmi_3d_len); + index += 2; + + if (hdmi_xx_len) { + /* Refer to HDMI Spec Ver 1.4a */ + index += hdmi_xx_len; + } + + if (hdmi_3d_len) { + int struct_all_3d = 0; + int mask_3d = 0xFF; + int vic_order_2d; + char struct_3d, detail_3d; + int i; + + hdmi_3d_len += index; + switch (temp & 0x60) { + case 0x40: + struct_all_3d = (block[index] << 8) + + block[index + 1]; + mask_3d = (block[index + 2] << 8) + + block[index + 3]; /* 3D support mask */ + DBGMSG("\t\t3D struct 0x%x,mask 0x%x\n", + struct_all_3d, mask_3d); + index += 4; + break; + case 0x20: + struct_all_3d = (block[index] << 8) + + block[index + 1]; + DBGMSG("\t\t3D struct 0x%x\n", struct_all_3d); + index += 2; + break; + default: + break; + } + /* 3D support type */ + if (struct_all_3d & BIT0) + DBGMSG("\t\tSupport Frame packing\n"); + if (struct_all_3d & BIT6) + DBGMSG("\t\tSupport Top and Bottom\n"); + if (struct_all_3d & BIT8) + DBGMSG("\t\tSupport Side by Side\n"); + + for (i = 0; i < 16; i++) { + if (mask_3d & (0x1 << i)) + info->vic_3d[i].mask = struct_all_3d; + } + + DBGMSG("\t\t[3D Structure type 0-Frame packing"); + DBGMSG(",6-Top and Bottom,8-Side by Side]\n"); + while (index < hdmi_3d_len) { + vic_order_2d = (block[index] & 0xF0) >> 4; + struct_3d = block[index] & 0x0F; + index++; + if (struct_3d & 0x8) { + detail_3d = (block[index] & 0xF0) >> 4; + index++; + } else { + detail_3d = 0; + } + info->vic_3d[vic_order_2d].mask |= + (0x1 << struct_3d); + DBGMSG("\t\tVIC %d,3D struct %d,detail %d\n", + vic_order_2d, struct_3d, detail_3d); + } + } + } +} + +static int edid_parse_CEA(char *edid, struct edid_info_t *info) +{ + char *block, *block_end; + char checksum = 0; + int i, len; + char audio_format; + int num = 0, sadcnt_in_block; + + memset(edid_parsed.sad, 0, sizeof(edid_parsed.sad)); + + if (edid[0] != 0x2) + return -1; + + for (i = 0; i < EDID_LENGTH; i++) + checksum += edid[i]; + + if (checksum != 0) { + DPRINT("*E* CEA EDID checksum (0x%02x) - data is corrupt\n", + checksum); + info->option |= (EDID_OPT_HDMI + EDID_OPT_AUDIO); + edid_dump(edid); + return -1; + } + + if(edid_msg_enable) + edid_dump(edid); + + DBGMSG("[EDID] CEA EDID Version %d.%d\n", edid[0], edid[1]); + + if (edid[1] >= 2) { + info->option |= (edid[3] & 0xF0); + DBGMSG("\t%s support 422\n", (edid[3] & 0x10) ? "" : "no"); + DBGMSG("\t%s support 444\n", (edid[3] & 0x20) ? "" : "no"); + DBGMSG("\t%s support audio\n", (edid[3] & 0x40) ? "" : "no"); + DBGMSG("\t%s support underscan\n", + (edid[3] & 0x80) ? "" : "no"); + } + + block_end = edid + edid[2]; + block = edid + 4; + do { + len = block[0] & 0x1F; + switch (((block[0] & 0xE0) >> 5)) { + case 1: /* Audio Data Block */ + DBGMSG("Audio Data Block (0x%02X)\n", block[0]); + info->option |= EDID_OPT_AUDIO; + sadcnt_in_block = len / 3; + + for (i = 0; i < sadcnt_in_block; i++) { + if (num < AUD_SAD_NUM) { + edid_parsed.sad[num].flag = 1; + edid_parsed.sad[num].sad_byte[0] = + block[i * 3 + 1]; + edid_parsed.sad[num].sad_byte[1] = + block[i * 3 + 2]; + edid_parsed.sad[num].sad_byte[2] = + block[i * 3 + 3]; + num++; + } else { + DPRINT("Lose SAD info:%02X %02X %02X\n", + block[i * 3 + 1], + block[i * 3 + 2], + block[i * 3 + 3]); + } + + DBGMSG("\t ======== SDA %d ========\n", i); + DBGMSG("\t SDA Data: 0x%02X 0x%02X 0x%02X\n", + block[i * 3 + 1], + block[i * 3 + 2], + block[i * 3 + 3]); + + audio_format = (block[i * 3 + 1] & 0x78) >> 3; + switch (audio_format) { + default: + case 0: /* reserved */ + case 15:/* reserved */ + DBGMSG("\t Reserved Audio Fmt\n"); + break; + case 1: /* LPCM */ + DBGMSG("\t Audio Fmt: LPCM\n"); + break; + case 2: /* AC3 */ + DBGMSG("\t Audio Fmt: AC3\n"); + break; + case 3: /* MPEG1 */ + DBGMSG("\t Audio Fmt: MPEG1\n"); + break; + case 4: /* MP3 */ + DBGMSG("\t Audio Fmt: MP3\n"); + break; + case 5: /* MPEG2 */ + DBGMSG("\t Audio Fmt: MPEG2\n"); + break; + case 6: /* AAC */ + DBGMSG("\t Audio Fmt: AAC\n"); + break; + case 7: /* DTS */ + DBGMSG("\t Audio Fmt: DTS\n"); + break; + case 8: /* ATRAC */ + DBGMSG("\t Audio Fmt: ATRAC\n"); + break; + case 9: /* One bit audio */ + DBGMSG("\t Audio Fmt: ONE BIT AUDIO\n"); + break; + case 10:/* Dolby */ + DBGMSG("\t Audio Fmt: DOLBY\n"); + break; + case 11:/* DTS-HD */ + DBGMSG("\t Audio Fmt: DTS-HD\n"); + break; + case 12:/* MAT (MLP) */ + DBGMSG("\t Audio Fmt: MAT\n"); + break; + case 13:/* DST */ + DBGMSG("\t Audio Fmt: DST\n"); + break; + case 14:/* WMA Pro */ + DBGMSG("\t Audio Fmt: WMA Pro\n"); + break; + } + + DBGMSG("\t Max channel: %d\n", + (block[i * 3 + 1] & 0x7) + 1); + DBGMSG("\t %s support 32 KHz\n", + (block[i * 3 + 2] & 0x1) ? "" : "no"); + DBGMSG("\t %s support 44 KHz\n", + (block[i * 3 + 2] & 0x2) ? "" : "no"); + DBGMSG("\t %s support 48 KHz\n", + (block[i * 3 + 2] & 0x4) ? "" : "no"); + DBGMSG("\t %s support 88 KHz\n", + (block[i * 3 + 2] & 0x8) ? "" : "no"); + DBGMSG("\t %s support 96 KHz\n", + (block[i * 3 + 2] & 0x10) ? "" : "no"); + DBGMSG("\t %s support 176 KHz\n", + (block[i * 3 + 2] & 0x20) ? "" : "no"); + DBGMSG("\t %s support 192 KHz\n", + (block[i * 3 + 2] & 0x40) ? "" : "no"); + if (audio_format == 1) { /* For LPCM */ + DBGMSG("\t %s support 16 bit\n", + (block[i * 3 + 3] & 0x1) ? + "" : "no"); + DBGMSG("\t %s support 20 bit\n", + (block[i * 3 + 3] & 0x2) ? + "" : "no"); + DBGMSG("\t %s support 24 bit\n", + (block[i * 3 + 3] & 0x4) ? + "" : "no"); + } else if (audio_format >= 2 && + audio_format <= 8) { + /* From AC3 to ATRAC */ + DBGMSG("\t Max bitrate: %d kbit/s\n", + block[i * 3 + 3] * 8); + } else if (audio_format >= 9 && + audio_format <= 14) { + /* From One-bit-audio to WMA Pro*/ + DBGMSG("\t Audio Format Code:0x%02X\n", + block[i * 3 + 3]); + } + DBGMSG("\t ========================\n"); + } + break; + case 2: /* Video Data Block */ + DBGMSG("Video Data Block\n"); + for (i = 0; i < len; i++) { + unsigned int vic; + + vic = block[1 + i] & 0x7F; + info->cea_vic[vic / 8] |= (0x1 << (vic % 8)); + if (i < 16) + info->vic_3d[i].vic = vic; + DBGMSG("\t %2d : VIC %2d %dx%d@%d%s %s\n", i, + vic, hdmi_vic_info[vic].resx, + hdmi_vic_info[vic].resy, + hdmi_vic_info[vic].freq, + (hdmi_vic_info[vic].option + & HDMI_VIC_INTERLACE) ? "I" : "P", + (hdmi_vic_info[vic].option + & HDMI_VIC_4x3) ? "4:3" : "16:9"); + } + break; + case 3: /* Vendor Spec Data Block */ + edid_parse_CEA_VendorSpecDataBlock(block, len, info); + break; + case 4: /* Speaker Allocation Data Block */ + DBGMSG("Speaker Allocation Data Block\n"); + break; + case 5: /* VESA DTC Data Block */ + DBGMSG("VESA DTC Data Block\n"); + break; + case 7: /* Use Extended Tag */ + DBGMSG("Use Extended Tag\n"); + break; + case 0: /* Reserved */ + default: + len = 0; + break; + } + block += (1 + len); + } while (block < block_end); + + { + struct fb_videomode *p; + unsigned int fps; + + DBGMSG("Detail Timing\n"); + block = edid + edid[2]; + len = (128 - edid[2]) / 18; + for (i = 0; i < len; i++, block += 18) { + p = &info->cea_timing[i]; + p->pixclock = ((block[1] << 8) + block[0]) * 10000; + if (p->pixclock == 0) + break; + p->xres = ((block[4] & 0xF0) << 4) + block[2]; + p->left_margin = ((block[4] & 0x0F) << 8) + block[3]; + p->yres = ((block[7] & 0xF0) << 4) + block[5]; + p->upper_margin = ((block[7] & 0x0F) << 8) + block[6]; + fps = vpp_calc_refresh(p->pixclock, p->xres + p->left_margin, + p->yres + p->upper_margin); + p->right_margin = ((block[11] & 0xC0) << 2) + block[8]; + p->hsync_len = ((block[11] & 0x30) << 4) + block[9]; + p->left_margin = p->left_margin - + p->right_margin - p->hsync_len; + p->lower_margin = ((block[11] & 0x0C) << 2) + + ((block[10] & 0xF0) >> 4); + p->vsync_len = ((block[11] & 0x03) << 4) + (block[10] & 0x0F); + p->upper_margin = p->upper_margin - + p->lower_margin - p->vsync_len; + p->refresh = fps; + p->vmode = (block[17] & 0x80) ? + FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED; + p->sync = (block[17] & 0x04) ? FB_SYNC_VERT_HIGH_ACT : 0; + p->sync |= (block[17] & 0x02) ? FB_SYNC_HOR_HIGH_ACT : 0; + if (p->vmode & FB_VMODE_INTERLACED) { + p->yres *= 2; + p->upper_margin *= 2; + p->lower_margin *= 2; + p->vsync_len *= 2; + } + DBGMSG("\t%dx%d%s@%d,clk %d\n", p->xres, p->yres, + (block[17] & 0x80) ? "I" : "P", fps, p->pixclock); + DBGMSG("\t\tH bp %d,sync %d,fp %d\n", + p->left_margin, p->hsync_len, p->right_margin); + DBGMSG("\t\tV bp %d,sync %d,fp %d\n", + p->upper_margin, p->vsync_len, p->lower_margin); + DBGMSG("\t\thsync %d,vsync %d\n", + (p->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0, + (p->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0); + p->pixclock = KHZ2PICOS(p->pixclock / 1000); + } + } + return 0; +} + +void edid_dump(char *edid) +{ + int i; + + DPRINT("===================== EDID BlOCK ====================="); + for (i = 0; i < 128; i++) { + if ((i % 16) == 0) + DPRINT("\n"); + DPRINT("%02x ", edid[i]); + } + DPRINT("\n"); + DPRINT("======================================================\n"); +} + +int edid_checksum(char *edid, int len) +{ + char checksum = 0; + int i; + + for (i = 0; i < len; i++) + checksum += edid[i]; + + if (checksum) { +#ifdef DEBUG + edid_dump(edid); +#endif + } + return checksum; +} + +int edid_parse(char *edid, struct edid_info_t *info) +{ + int ext_cnt = 0; + + if (edid == 0) + return 0; + + if (info->option & EDID_OPT_VALID) { + DBG_MSG("[EDID] parse exist\n"); + return info->option; + } + + DBG_MSG("[EDID] Enter\n"); + + memset(info, 0, sizeof(struct edid_info_t)); + info->option = EDID_OPT_VALID; + if (edid_parse_v1(edid, info) == 0) { + ext_cnt = edid[0x7E]; + if (ext_cnt >= EDID_BLOCK_MAX) { + DPRINT("[EDID] *W* ext block cnt %d\n", ext_cnt); + ext_cnt = EDID_BLOCK_MAX - 1; + } + } else { + info->option = 0; + return 0; + } + + while (ext_cnt) { + edid += 128; + ext_cnt--; + if (edid_parse_CEA(edid, info) == 0) + continue; + + DPRINT("*W* not support EDID\n"); + edid_dump(edid); + } + return info->option; +} + +int edid_find_support(struct edid_info_t *info, unsigned int resx, + unsigned int resy, int freq, struct fb_videomode **vmode) +{ + struct fb_videomode *p; + int temp; + int ret; + int i; + + ret = 0; + *vmode = 0; + + if (!info) + return 0; + + /* find detail timing */ + for (i = 0; i < 4; i++) { + p = &info->detail_timing[i]; + if (p->pixclock == 0) + continue; + if (resx != p->xres) + continue; + if (resy != p->yres) + continue; + + temp = p->refresh; + temp |= (p->vmode & FB_VMODE_INTERLACED) ? + EDID_TMR_INTERLACE : 0; + if (freq != temp) + continue; + *vmode = p; + ret = 3; + goto find_end; + } + + /* find cea timing */ + for (i = 0; i < 6; i++) { + p = &info->cea_timing[i]; + + if (p->pixclock == 0) + continue; + if (resx != p->xres) + continue; + if (resy != p->yres) + continue; + + temp = p->refresh; + temp |= (p->vmode & FB_VMODE_INTERLACED) ? + EDID_TMR_INTERLACE : 0; + if (freq != temp) + continue; + + *vmode = p; + ret = 4; + goto find_end; + } + + /* find vic timing */ + for (i = 0; i < 64; i++) { + if ((info->cea_vic[i / 8] & (0x1 << (i % 8))) == 0) + continue; + + if (i >= HDMI_VIDEO_CODE_MAX) + continue; + + if (resx != hdmi_vic_info[i].resx) + continue; + if (resy != hdmi_vic_info[i].resy) + continue; + temp = hdmi_vic_info[i].freq; + temp |= (hdmi_vic_info[i].option & HDMI_VIC_INTERLACE) ? + EDID_TMR_INTERLACE : 0; + if (freq != temp) + continue; + ret = 5; + goto find_end; + } + + /* find established timing */ + if (info->establish_timing) { + for (i = 0; i < 17; i++) { + if (info->establish_timing & (0x1 << i)) { + if ((resx == edid_establish_timing[i].resx) && + (resy == edid_establish_timing[i].resy)) { + if (freq == + edid_establish_timing[i].freq) { + ret = 1; + goto find_end; + } + } + } + } + } + + /* find standard timing */ + for (i = 0; i < 8; i++) { + if (info->standard_timing[i].resx == 0) + continue; + if ((resx == info->standard_timing[i].resx) && + (resy == info->standard_timing[i].resy)) { + if (freq == info->standard_timing[i].freq) { + ret = 2; + goto find_end; + } + } + } + +find_end: +#if 0 + if ((resx == 1920) && (resy == 1080) && !(freq & EDID_TMR_INTERLACE)) + ret = 0; +#endif +#if 0 + if (!(freq & EDID_TMR_INTERLACE)) + ret = 0; +#endif +#if 0 + DPRINT("[EDID] %s support %dx%d@%d%s(ret %d)\n", + (ret) ? "" : "No", resx, resy, freq & EDID_TMR_FREQ, + (freq & EDID_TMR_INTERLACE) ? "I" : "P", ret); +#endif + return ret; +} + +unsigned int edid_get_hdmi_phy_addr(void) +{ + struct vout_t *vo; + + vo = vout_get_entry(VPP_VOUT_NUM_HDMI); + return vo->edid_info.hdmi_phy_addr; +} + +unsigned int edid_get_hdmi_3d_mask(struct edid_info_t *info, int vic) +{ + int i; + + if (!info) + return 0; + for (i = 0; i < 16; i++) { + if (info->vic_3d[i].vic == vic) + return info->vic_3d[i].mask; + } + return 0; +} + diff --git a/common/wmt_display/pwm.c b/common/wmt_display/pwm.c new file mode 100755 index 0000000..d19cd50 --- /dev/null +++ b/common/wmt_display/pwm.c @@ -0,0 +1,306 @@ +/*++ + * linux/drivers/video/wmt/lcd.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2010 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +/* + * ChangeLog + * + * 2010-08-05 Sam Shen <samshen@wondermedia.com.tw> + * * Add License declaration and ChangeLog + */ + + +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "vpp.h" +#include "wmt_display.h" +/*----------------------- Backlight --------------------------------------*/ +#ifdef CONFIG_VPP_SHENZHEN +#include "../../board/wmt/include/wmt_iomux.h" + +#define ENV_LOGO_LED "wmt.logo.led" + +static void logo_led_power_on(int on); +#endif + +#define pwm_write_reg(addr,val,wait) \ + REG32_VAL(addr) = val; \ + while(REG32_VAL(0xd8220040)&=wait); + +#define UBOOT_PWM_INVERT 0x10 +void lcd_blt_enable(int no,int enable) +{ +#ifdef CONFIG_VPP_SHENZHEN + lcd_backlight_power_on(enable != 0); +#endif + pwm_set_enable(no,enable); + +#ifdef CONFIG_VPP_SHENZHEN + logo_led_power_on(enable); +#endif + +} /* End of vt8430_blt_enable */ + +void lcd_blt_set_level(int no,int level) +{ + return; +} + +void lcd_blt_set_freq(int no,unsigned int freq) +{ + return; +} + +void lcd_blt_set_pwm(int no, int level, int freq) +{ + int clock = auto_pll_divisor(DEV_PWM,GET_FREQ, 0, 0); + int period, duty, scalar; + + clock = clock / freq; + scalar = 0; + period = 2000; + + while(period > 1023) { + scalar++; + period = clock / scalar; + } + + duty = (period*level)/100; + duty = (duty)? (duty-1):0; + scalar = scalar-1; + period = period -1; + + pwm_set_period(no,period); + pwm_set_duty(no,duty); + pwm_set_scalar(no,scalar); + if ((g_pwm_setting.config&UBOOT_PWM_INVERT) != 0) + pwm_set_control(no,(level)? 0x37:0x8); + else + pwm_set_control(no,(level)? 0x35:0x8); + pwm_set_gpio(no,level); +} + +void pwm_set_enable(int no,int enable) +{ + unsigned int addr,reg,reg1; + + addr = PWM_CTRL_REG_ADDR + (0x10 * no); + reg = REG32_VAL(addr); + if( enable ){ + reg |= PWM_ENABLE; + } + else { + reg &= ~PWM_ENABLE; + } + + pwm_write_reg(addr,reg,PWM_CTRL_UPDATE << (4*no)); + reg1 = REG32_VAL(addr); + pwm_set_gpio(no,enable); +} + +void pwm_set_control(int no,unsigned int ctrl) +{ + unsigned int addr; + + addr = PWM_CTRL_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,ctrl,PWM_CTRL_UPDATE << (8*no)); +} /* End of pwm_proc */ + +void pwm_set_scalar(int no,unsigned int scalar) +{ + unsigned int addr; + + addr = PWM_SCALAR_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,scalar,PWM_SCALAR_UPDATE << (8*no)); +} + +void pwm_set_period(int no,unsigned int period) +{ + unsigned int addr; + + addr = PWM_PERIOD_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,period,PWM_PERIOD_UPDATE << (8*no)); +} + +void pwm_set_duty(int no,unsigned int duty) +{ + unsigned int addr; + + addr = PWM_DUTY_REG_ADDR + (0x10 * no); + pwm_write_reg(addr,duty,PWM_DUTY_UPDATE << (8*no)); +} + +unsigned int pwm_get_period(int no) +{ + unsigned int addr; + + addr = PWM_PERIOD_REG_ADDR + (0x10 * no); + return (REG32_VAL(addr) & 0xFFF); +} + +unsigned int pwm_get_duty(int no) +{ + unsigned int addr; + + addr = PWM_DUTY_REG_ADDR + (0x10 * no); + return (REG32_VAL(addr) & 0xFFF); +} + +unsigned int pwm_get_enable(int no) +{ + unsigned int addr,reg; + + addr = PWM_CTRL_REG_ADDR + (0x10 * no); + reg = REG32_VAL(addr); + reg &= PWM_ENABLE; + return reg; +} + +void set_lcd_power(int on) +{ + unsigned int val; + + if ((g_lcd_pw_pin.ctl == 0) || (g_lcd_pw_pin.oc == 0) || (g_lcd_pw_pin.od == 0)) { + printf("lcd power ping not define\n"); + return; + } + val = 1<<g_lcd_pw_pin.bitmap; + if (g_lcd_pw_pin.act == 0) + on = ~on; + REG32_VAL(g_lcd_pw_pin.ctl) |= val; + REG32_VAL(g_lcd_pw_pin.oc) |= val; + if (on) { + REG32_VAL(g_lcd_pw_pin.od) |= val; + } else { + REG32_VAL(g_lcd_pw_pin.od) &= ~val; + } +} + +void pwm_set_gpio(int no,int enable) +{ + /* unsigned int pwm_pin; */ + + if( enable ) { + if((g_pwm_setting.config&UBOOT_PWM_INVERT) != 0) + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) &= 0xFE; + else + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) |= 0x01; + + REG8_VAL(GPIO_OC_GP20_PWM0_BYTE_ADDR) &= 0xFE; + REG8_VAL(GPIO_CTRL_GP20_PWM0_BYTE_ADDR) &= 0xFE; + } else { + if((g_pwm_setting.config&UBOOT_PWM_INVERT) != 0) + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) |= 0x01; + else + REG8_VAL(GPIO_OD_GP20_PWM0_BYTE_ADDR) &= 0xFE; + + REG8_VAL(GPIO_OC_GP20_PWM0_BYTE_ADDR) |= 0x01; + REG8_VAL(GPIO_CTRL_GP20_PWM0_BYTE_ADDR) |= 0x01; + } + /* set to PWM mode */ + if ( no == 0 ) + REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x1000; + else if( no == 1 ) + REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x80; + /* do not control back-light power in pwm */ + /* + pwm_pin = REG32_VAL(PWM_CTRL_REG_ADDR + (0x10 * no)); + if (((pwm_pin&PWM_ENABLE) != 0)&&(enable == 1)) + set_lcd_power(1); + if (((pwm_pin&PWM_ENABLE) == 0)&&(enable == 0)) + set_lcd_power(0); + */ +} + +#ifdef CONFIG_VPP_SHENZHEN + +static void logo_led_set_pwm(int no, int level, int freq, int active, int init) +{ + int clock; + int period, duty, scalar; + + if(init) { + clock = auto_pll_divisor(DEV_PWM,GET_FREQ, 0, 0); + clock = clock / freq; + scalar = 0; + period = 2000; + + while(period > 1023) { + scalar++; + period = clock / scalar; + } + + duty = (period*level)/100; + duty = (duty)? (duty-1):0; + scalar = scalar-1; + period = period -1; + + pwm_set_period(no,period); + pwm_set_duty(no,duty); + pwm_set_scalar(no,scalar); + REG32_VAL(PIN_SHARING_SEL_4BYTE_ADDR) &= ~0x80; + } + + if (active == 0) + pwm_set_control(no,(level)? 0x37:0x8); + else + pwm_set_control(no,(level)? 0x35:0x8); +} + +#define PWM2_GPIO_NO 200 + +static void logo_led_power_on(int on) +{ + int ret; + static int led_init; + static struct gpio_param_t led_control_pin; + + if(led_init == -1) + return; + + if(led_init == 0) { + ret = parse_gpio_param(ENV_LOGO_LED, &led_control_pin); + if(ret) { + led_init = -1; + return; + } + + led_init = 1; + } + + switch (led_control_pin.gpiono) { + case PWM2_GPIO_NO: + if(on) + logo_led_set_pwm(2, 100, 220000, led_control_pin.act, 1); + else + logo_led_set_pwm(2, 100, 220000, !led_control_pin.act, 1); + break; + + default: + if(on) + gpio_direction_output(led_control_pin.gpiono, led_control_pin.act); + else + gpio_direction_output(led_control_pin.gpiono, !led_control_pin.act); + break; + } +} +#endif + diff --git a/common/wmt_display/scl.c b/common/wmt_display/scl.c new file mode 100755 index 0000000..f367a0d --- /dev/null +++ b/common/wmt_display/scl.c @@ -0,0 +1,1556 @@ +/*++ + * linux/drivers/video/wmt/scl.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define SCL_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ + +#include "scl.h" + +HW_REG struct scl_base1_regs *scl_regs1 = (void *) SCL_BASE_ADDR; +HW_REG struct scl_base2_regs *scl_regs2 = (void *) SCL_BASE2_ADDR; + +#ifdef WMT_FTBLK_SCL +void scl_reg_dump(void) +{ + vpp_set_clock_enable(DEV_SCL444U, 1, 0); + + DPRINT("========== SCL register dump ==========\n"); + vpp_reg_dump(REG_SCL_BASE1_BEGIN, + REG_SCL_BASE1_END - REG_SCL_BASE1_BEGIN); + vpp_reg_dump(REG_SCL_BASE2_BEGIN, + REG_SCL_BASE2_END - REG_SCL_BASE2_BEGIN); + + DPRINT("---------- SCL scale ----------\n"); + DPRINT("scale enable %d\n", scl_regs1->en.b.alu_enable); + DPRINT("mode bilinear(H %d,V %d),recursive(H %d,V %d)\n", + scl_regs1->true_bilinear.b.h, scl_regs1->true_bilinear.b.v, + scl_regs2->recursive_mode.b.h, scl_regs2->recursive_mode.b.v); + DPRINT("src(%d,%d),dst(%d,%d)\n", + scl_regs1->r_h_size.b.pix_w, scl_regs1->vxwidth.b.vxwidth, + scl_regs1->hscale1.b.thr, scl_regs1->vscale1.b.thr); + DPRINT("scale width H %d,V %d\n", + scl_regs1->hxwidth.b.hxwidth, scl_regs1->vxwidth.b.vxwidth); + DPRINT("H scale up %d,V scale up %d\n", + scl_regs1->sclup_en.b.h, scl_regs1->sclup_en.b.v); + DPRINT("H sub step %d,thr %d,step %d,sub step cnt %d,i step cnt %d\n", + scl_regs1->hscale1.b.substep, scl_regs1->hscale1.b.thr, + scl_regs1->hscale2.b.step, scl_regs1->hscale2.b.substepcnt, + scl_regs1->hscale3.b.stepcnt); + DPRINT("V sub step %d,thr %d,step %d,sub step cnt %d,i step cnt %d\n", + scl_regs1->vscale1.b.substep, scl_regs1->vscale1.b.thr, + scl_regs1->vscale2.b.step, scl_regs1->vscale2.b.substepcnt, + scl_regs1->vscale3.b.stepcnt); + + DPRINT("---------- SCL filter ----------\n"); + DPRINT("DEBLOCK %d,boundary 1st 0x%x,2nd 0x%x\n,", + scl_regs2->field_mode.b.deblock, + scl_regs2->dblk_threshold.b.layer1_boundary, + scl_regs2->dblk_threshold.b.layer2_boundary); + DPRINT("FIELD DEFLICKER %d,up %s down,thr Y %d,C %d\n", + scl_regs2->field_mode.b.field_deflicker, + (scl_regs2->field_mode.b.field_deflicker) ? "&" : "or", + scl_regs2->field_flicker.b.y_thd, + scl_regs2->field_flicker.b.c_thd); + DPRINT("FRAME DEFLICKER %d,%s,2^%d,scene chg %d\n", + scl_regs2->field_mode.b.frame_deflicker, + (scl_regs2->frame_flicker.b.rgb) ? "RGB" : "Y", + scl_regs2->frame_flicker.b.sampler, + scl_regs2->frame_flicker.b.scene_chg_thd); + DPRINT("CSC enable %d,CSC clamp %d\n", + scl_regs2->csc_ctl.b.enable, + scl_regs2->csc_ctl.b.clamp_enable); + DPRINT("---------- SCL TG ----------\n"); + DPRINT("TG source : %s\n", + (scl_regs1->tg_govw.b.enable) ? "GOVW" : "SCL"); + DPRINT("TG enable %d, wait ready enable %d\n", + scl_regs1->tg_ctl.b.enable, + scl_regs1->tg_ctl.b.watchdog_enable); + DPRINT("clk %d,Read cyc %d,1T %d\n", + vpp_get_base_clock(VPP_MOD_SCL), + scl_regs1->tg_ctl.b.rdcyc, scl_regs2->readcyc_1t.b.rdcyc_1t); + DPRINT("H total %d, beg %d, end %d\n", + scl_regs1->tg_total.b.h_allpixel, + scl_regs1->tg_h_active.b.h_actbg, + scl_regs1->tg_h_active.b.h_actend); + DPRINT("V total %d, beg %d, end %d\n", + scl_regs1->tg_total.b.v_allline, + scl_regs1->tg_v_active.b.v_actbg, + scl_regs1->tg_v_active.b.v_actend); + DPRINT("VBIE %d,PVBI %d\n", + scl_regs1->tg_vbi.b.vbie, scl_regs1->tg_vbi.b.pvbi); + DPRINT("Watch dog 0x%x\n", + scl_regs1->tg_watchdog); + DPRINT("---------- SCLR FB ----------\n"); + DPRINT("SCLR MIF enable %d\n", + scl_regs1->r_ctl.b.mif_enable); + DPRINT("color format %s\n", vpp_colfmt_str[sclr_get_color_format()]); + DPRINT("color bar enable %d,mode %d,inv %d\n", + scl_regs1->r_ctl.b.colorbar_enable, + scl_regs1->r_ctl.b.colorbar_mode, + scl_regs1->r_ctl.b.colorbar_inv); + DPRINT("sourc mode : %s,H264 %d\n", + (scl_regs1->r_ctl.b.field) ? "field" : "frame", + scl_regs1->r_ctl.b.h264); + DPRINT("Y addr 0x%x, C addr 0x%x\n", + scl_regs1->r_ysa, scl_regs1->r_csa); + DPRINT("width %d, fb width %d\n", + scl_regs1->r_h_size.b.pix_w, scl_regs1->r_h_size.b.fb_w); + DPRINT("H crop %d, V crop %d\n", + scl_regs1->r_crop.b.hcrop, scl_regs1->r_crop.b.vcrop); + DPRINT("---------- SCLW FB ----------\n"); + DPRINT("SCLW MIF enable %d\n", scl_regs1->w_ctl.b.mif_enable); + DPRINT("color format %s\n", vpp_colfmt_str[sclw_get_color_format()]); + DPRINT("Y addr 0x%x, C addr 0x%x\n", + scl_regs1->w_ysa, scl_regs1->w_csa); + DPRINT("Y width %d, fb width %d\n", + scl_regs1->w_y_time.b.pxl_w, scl_regs1->w_y_time.b.fb_w); + DPRINT("C width %d, fb width %d\n", + scl_regs1->w_c_time.b.pxl_w, scl_regs1->w_c_time.b.fb_w); + DPRINT("Y err %d, C err %d\n", + scl_regs1->w_ff_ctl.b.mif_y_err, + scl_regs1->w_ff_ctl.b.mif_c_err); + DPRINT("---------- SCLR2 FB ----------\n"); + DPRINT("MIF enable %d\n", scl_regs1->r2_ctl.b.mif_en); + DPRINT("color format %s\n", vpp_colfmt_str[scl_R2_get_color_format()]); + DPRINT("color bar enable %d,mode %d,inv %d\n", + scl_regs1->r2_ctl.b.color_en, + scl_regs1->r2_ctl.b.color_wide, + scl_regs1->r2_ctl.b.color_inv); + DPRINT("sourc mode : %s,H264 %d\n", + (scl_regs1->r2_ctl.b.iofmt) ? "field" : "frame", + scl_regs1->r2_ctl.b.h264_fmt); + DPRINT("Y addr 0x%x, C addr 0x%x\n", + scl_regs1->r2_ysa, scl_regs1->r2_csa); + DPRINT("width %d, fb width %d\n", + scl_regs1->r2_h_size.b.lnsize, scl_regs1->r2_h_size.b.fbw); + DPRINT("H crop %d, V crop %d\n", + scl_regs1->r2_crop.b.hcrop, scl_regs1->r2_crop.b.vcrop); + DPRINT("---------- ALPHA ----------\n"); + DPRINT("src alpha %d,dst alpha %d,swap %d\n", + scl_regs1->alpha_md.b.src, + scl_regs1->alpha_md.b.dst, + scl_regs1->alpha_md.b.swap); + DPRINT("src fix 0x%x,dst fix 0x%x\n", + scl_regs1->alpha_fxd.b.src_fixed, + scl_regs1->alpha_fxd.b.dst_fixed); + DPRINT("---------- ColorKey ----------\n"); + DPRINT("enable %d\n", scl_regs1->alpha_colorkey.b.enable); + DPRINT("from %s,comp %d,mode %d\n", + (scl_regs1->alpha_colorkey.b.from) ? "mif2" : "mif1", + scl_regs1->alpha_colorkey.b.comp, + scl_regs1->alpha_colorkey.b.mode); + DPRINT("R 0x%x,G 0x%x,B 0x%x\n", + scl_regs1->alpha_colorkey_rgb.b.r, + scl_regs1->alpha_colorkey_rgb.b.g, + scl_regs1->alpha_colorkey_rgb.b.b); + DPRINT("---------- sw status ----------\n"); + DPRINT("complete %d\n", p_scl->scale_complete); + + vpp_set_clock_enable(DEV_SCL444U, 0, 0); +} + +void scl_set_enable(vpp_flag_t enable) +{ + scl_regs1->en.b.alu_enable = enable; +} + +void scl_set_reg_update(vpp_flag_t enable) +{ + scl_regs1->upd.b.reg_update = enable; +} + +void scl_set_reg_level(vpp_reglevel_t level) +{ + scl_regs1->sel.b.reg_level = level; +} + +void scl_set_int_enable(vpp_flag_t enable, enum vpp_int_t int_bit) +{ + /* clean status first before enable/disable interrupt */ + scl_clean_int_status(int_bit); + + if (int_bit & VPP_INT_ERR_SCL_TG) + scl_regs1->w_int_en.b.tg_err = enable; + if (int_bit & VPP_INT_ERR_SCLR1_MIF) + scl_regs1->w_int_en.b.r1_mif_enable = enable; + if (int_bit & VPP_INT_ERR_SCLR2_MIF) + scl_regs1->w_int_en.b.r2_mif_enable = enable; + if (int_bit & VPP_INT_ERR_SCLW_MIFRGB) + scl_regs1->w_int_en.b.mif_rgb_err = enable; + if (int_bit & VPP_INT_ERR_SCLW_MIFY) + scl_regs1->w_int_en.b.mif_y_err = enable; + if (int_bit & VPP_INT_ERR_SCLW_MIFC) + scl_regs1->w_int_en.b.mif_c_err = enable; +} + +enum vpp_int_err_t scl_get_int_status(void) +{ + enum vpp_int_err_t int_sts; + + int_sts = 0; + if (scl_regs1->tg_sts.b.tgerr) + int_sts |= VPP_INT_ERR_SCL_TG; + if (scl_regs1->r_fifo_ctl.b.r1_mif_err) + int_sts |= VPP_INT_ERR_SCLR1_MIF; + if (scl_regs1->r_fifo_ctl.b.r2_mif_err) + int_sts |= VPP_INT_ERR_SCLR2_MIF; + if (scl_regs1->w_ff_ctl.b.mif_rgb_err) + int_sts |= VPP_INT_ERR_SCLW_MIFRGB; + if (scl_regs1->w_ff_ctl.b.mif_y_err) + int_sts |= VPP_INT_ERR_SCLW_MIFY; + if (scl_regs1->w_ff_ctl.b.mif_c_err) + int_sts |= VPP_INT_ERR_SCLW_MIFC; + return int_sts; +} + +void scl_clean_int_status(enum vpp_int_err_t int_sts) +{ + if (int_sts & VPP_INT_ERR_SCL_TG) + scl_regs1->tg_sts.val = BIT0; + if (int_sts & VPP_INT_ERR_SCLR1_MIF) + scl_regs1->r_fifo_ctl.val = + (scl_regs1->r_fifo_ctl.val & ~0x300) | BIT8; + if (int_sts & VPP_INT_ERR_SCLR2_MIF) + scl_regs1->r_fifo_ctl.val = + (scl_regs1->r_fifo_ctl.val & ~0x300) | BIT9; + if (int_sts & VPP_INT_ERR_SCLW_MIFRGB) + scl_regs1->w_ff_ctl.val = BIT16; + if (int_sts & VPP_INT_ERR_SCLW_MIFY) + scl_regs1->w_ff_ctl.val = BIT8; + if (int_sts & VPP_INT_ERR_SCLW_MIFC) + scl_regs1->w_ff_ctl.val = BIT0; +} + +void scl_set_csc_mode(vpp_csc_t mode) +{ + vdo_color_fmt src_fmt, dst_fmt; + + src_fmt = sclr_get_color_format(); + dst_fmt = sclw_get_color_format(); + mode = vpp_check_csc_mode(mode, src_fmt, dst_fmt, 0); + if (p_scl->abgr_mode) { + unsigned int parm[5]; + + parm[0] = (vpp_csc_parm[mode][1] & 0xFFFF) | + (vpp_csc_parm[mode][0] & 0xFFFF0000); /* C3,C2 */ + parm[1] = (vpp_csc_parm[mode][0] & 0xFFFF) | + (vpp_csc_parm[mode][2] & 0xFFFF0000); /* C1,C6 */ + parm[2] = (vpp_csc_parm[mode][2] & 0xFFFF) | + (vpp_csc_parm[mode][1] & 0xFFFF0000); /* C5,C4 */ + parm[3] = (vpp_csc_parm[mode][4] & 0xFFFF) | + (vpp_csc_parm[mode][3] & 0xFFFF0000); /* C9,C8 */ + parm[4] = (vpp_csc_parm[mode][3] & 0xFFFF) | + (vpp_csc_parm[mode][4] & 0xFFFF0000); /* C7,I */ + + scl_regs2->csc1 = parm[0]; + scl_regs2->csc2 = parm[1]; + scl_regs2->csc3 = parm[2]; + scl_regs2->csc4 = parm[3]; + scl_regs2->csc5 = parm[4]; + } else { + scl_regs2->csc1 = vpp_csc_parm[mode][0]; + scl_regs2->csc2 = vpp_csc_parm[mode][1]; + scl_regs2->csc3 = vpp_csc_parm[mode][2]; + scl_regs2->csc4 = vpp_csc_parm[mode][3]; + scl_regs2->csc5 = vpp_csc_parm[mode][4]; + } + scl_regs2->csc6 = vpp_csc_parm[mode][5]; + scl_regs2->csc_ctl.val = vpp_csc_parm[mode][6]; + scl_regs2->csc_ctl.b.enable = (mode >= VPP_CSC_MAX) ? 0 : 1; +} + +void scl_set_scale_enable(vpp_flag_t vscl_enable, vpp_flag_t hscl_enable) +{ + DBGMSG("V %d,H %d\n", vscl_enable, hscl_enable); + scl_regs1->sclup_en.b.v = vscl_enable; + scl_regs1->sclup_en.b.h = hscl_enable; +} + +void scl_set_V_scale(int A, int B) /* A dst,B src */ +{ + unsigned int V_STEP; + unsigned int V_SUB_STEP; + unsigned int V_THR_DIV2; + + DBG_DETAIL("scl_set_V_scale(%d,%d)\r\n", A, B); + if (A > B) { + V_STEP = (B - 1) * 16 / A; + V_SUB_STEP = (B - 1) * 16 % A; + } else { + V_STEP = (16 * B / A); + V_SUB_STEP = ((16 * B) % A); + } + V_THR_DIV2 = A; + + DBG_DETAIL("V step %d,sub step %d, div2 %d\r\n", + V_STEP, V_SUB_STEP, V_THR_DIV2); + + scl_regs1->vxwidth.b.dst_vxwidth = (A > B) ? A : B; + scl_regs1->vxwidth.b.vxwidth = B; + scl_regs1->vscale2.b.step = V_STEP; + scl_regs1->vscale1.b.substep = V_SUB_STEP; + scl_regs1->vscale1.b.thr = V_THR_DIV2; + scl_regs1->vscale2.b.substepcnt = 0; +} + +void scl_set_H_scale(int A, int B) /* A dst,B src */ +{ + unsigned int H_STEP; + unsigned int H_SUB_STEP; + unsigned int H_THR_DIV2; + + DBG_DETAIL("scl_set_H_scale(%d,%d)\r\n", A, B); + if (A > B) { + H_STEP = (B - 1) * 16 / A; + H_SUB_STEP = (B - 1) * 16 % A; + } else { + H_STEP = (16 * B / A); + H_SUB_STEP = ((16 * B) % A); + } + H_THR_DIV2 = A; + DBG_DETAIL("H step %d,sub step %d, div2 %d\r\n", + H_STEP, H_SUB_STEP, H_THR_DIV2); + scl_regs1->hxwidth.b.hxwidth = ((A > B) ? A : B); + scl_regs1->hscale2.b.step = H_STEP; + scl_regs1->hscale1.b.substep = H_SUB_STEP; + scl_regs1->hscale1.b.thr = H_THR_DIV2; + scl_regs1->hscale2.b.substepcnt = 0; +} + +void scl_set_crop(int offset_x, int offset_y) +{ + /* offset_x &= VPU_CROP_ALIGN_MASK; */ /* ~0x7 */ + offset_x &= ~0xf; + + scl_regs1->hscale3.b.stepcnt = offset_x * 16; + scl_regs1->vscale3.b.stepcnt = offset_y * 16; + DBGMSG("[VPU] crop - x : 0x%x, y : 0x%x \r\n", + offset_x * 16, offset_y * 16); +} + +void scl_set_tg_enable(vpp_flag_t enable) +{ + scl_regs1->tg_ctl.b.enable = enable; +} + +unsigned int scl_set_clock(unsigned int pixel_clock) +{ + unsigned int rd_cyc; + rd_cyc = vpp_get_base_clock(VPP_MOD_SCL) / pixel_clock; + return rd_cyc; +} + +void scl_set_timing(vpp_clock_t *timing, unsigned int pixel_clock) +{ +#if 1 + timing->read_cycle = WMT_SCL_RCYC_MIN; +#else + timing->read_cycle = scl_set_clock(pixel_clock * 2) - 1; + timing->read_cycle = (timing->read_cycle < WMT_SCL_RCYC_MIN) ? + WMT_SCL_RCYC_MIN : timing->read_cycle; + timing->read_cycle = (timing->read_cycle > 255) ? + 0xFF : timing->read_cycle; +#endif + scl_regs1->tg_ctl.b.rdcyc = timing->read_cycle; + scl_regs2->readcyc_1t.b.rdcyc_1t = (timing->read_cycle) ? 0 : 1; + scl_regs1->tg_total.b.h_allpixel = timing->total_pixel_of_line; + scl_regs1->tg_h_active.b.h_actbg = timing->begin_pixel_of_active; + scl_regs1->tg_h_active.b.h_actend = timing->end_pixel_of_active; + scl_regs1->tg_total.b.v_allline = timing->total_line_of_frame; + scl_regs1->tg_v_active.b.v_actbg = timing->begin_line_of_active; + scl_regs1->tg_v_active.b.v_actend = timing->end_line_of_active; + scl_regs1->tg_vbi.b.vbie = timing->line_number_between_VBIS_VBIE; + scl_regs1->tg_vbi.b.pvbi = timing->line_number_between_PVBI_VBIS; +#ifdef DEBUG_DETAIL + vpp_show_timing("scl set timing", 0, timing); +#endif +} + +void scl_get_timing(vpp_clock_t *p_timing) +{ + p_timing->read_cycle = scl_regs1->tg_ctl.b.rdcyc; + p_timing->total_pixel_of_line = scl_regs1->tg_total.b.h_allpixel; + p_timing->begin_pixel_of_active = scl_regs1->tg_h_active.b.h_actbg; + p_timing->end_pixel_of_active = scl_regs1->tg_h_active.b.h_actend; + p_timing->total_line_of_frame = scl_regs1->tg_total.b.v_allline; + p_timing->begin_line_of_active = scl_regs1->tg_v_active.b.v_actbg; + p_timing->end_line_of_active = scl_regs1->tg_v_active.b.v_actend; + p_timing->line_number_between_VBIS_VBIE = scl_regs1->tg_vbi.b.vbie; + p_timing->line_number_between_PVBI_VBIS = scl_regs1->tg_vbi.b.pvbi; +} + +void scl_set_watchdog(U32 count) +{ + if (0 != count) { + scl_regs1->tg_watchdog = count; + scl_regs1->tg_ctl.b.watchdog_enable = 1; + } else + scl_regs1->tg_ctl.b.watchdog_enable = 0; +} + +void scl_set_timing_master(vpp_mod_t mod_bit) +{ + scl_regs1->tg_govw.b.enable = (mod_bit == VPP_MOD_GOVW) ? 1 : 0; +} + +vpp_mod_t scl_get_timing_master(void) +{ + return (scl_regs1->tg_govw.b.enable) ? VPP_MOD_GOVW : VPP_MOD_SCL; +} + +void scl_set_drop_line(vpp_flag_t enable) +{ + scl_regs1->scldw = enable; +} + +/* only one feature can work, other should be disable */ +void scl_set_filter_mode(enum vpp_filter_mode_t mode, int enable) +{ + DBG_DETAIL("(%d,%d)\n", mode, enable); + if (mode != VPP_FILTER_SCALE) { + if (scl_regs1->sclup_en.b.v || scl_regs1->sclup_en.b.h) + DPRINT("[SCL] *W* filter can't work w scale\n"); + } + scl_regs2->field_mode.b.deblock = 0; + scl_regs2->field_mode.b.field_deflicker = 0; + scl_regs2->field_mode.b.frame_deflicker = 0; + switch (mode) { + default: + case VPP_FILTER_SCALE: /* scale mode */ + break; + case VPP_FILTER_DEBLOCK: /* deblock */ + scl_regs2->field_mode.b.deblock = enable; + break; + case VPP_FILTER_FIELD_DEFLICKER: /* field deflicker */ + scl_regs2->field_mode.b.field_deflicker = enable; + break; + case VPP_FILTER_FRAME_DEFLICKER: /* frame deflicker */ + scl_regs2->field_mode.b.frame_deflicker = enable; + break; + } +} + +enum vpp_filter_mode_t scl_get_filter_mode(void) +{ + if (scl_regs1->sclup_en.b.v || scl_regs1->sclup_en.b.h) + return VPP_FILTER_SCALE; + + if (scl_regs2->field_mode.b.deblock) + return VPP_FILTER_DEBLOCK; + + if (scl_regs2->field_mode.b.field_deflicker) + return VPP_FILTER_FIELD_DEFLICKER; + + if (scl_regs2->field_mode.b.frame_deflicker) + return VPP_FILTER_FRAME_DEFLICKER; + return VPP_FILTER_SCALE; +} + +void sclr_set_mif_enable(vpp_flag_t enable) +{ + scl_regs1->r_ctl.b.mif_enable = enable; +} + +void sclr_set_mif2_enable(vpp_flag_t enable) +{ + +} + +void sclr_set_colorbar(vpp_flag_t enable, int width, int inverse) +{ + scl_regs1->r_ctl.b.colorbar_mode = width; + scl_regs1->r_ctl.b.colorbar_inv = inverse; + scl_regs1->r_ctl.b.colorbar_enable = enable; +} + +void sclr_set_field_mode(vpp_display_format_t fmt) +{ + scl_regs1->r_ctl.b.src_disp_fmt = fmt; +} + +void sclr_set_display_format(vpp_display_format_t source, + vpp_display_format_t target) +{ + scl_regs1->r_ctl.b.src_disp_fmt = + (source == VPP_DISP_FMT_FIELD) ? 1 : 0; + scl_regs1->r_ctl.b.field = (target == VPP_DISP_FMT_FIELD) ? 1 : 0; +} + +void sclr_set_color_format(vdo_color_fmt format) +{ + p_scl->abgr_mode = 0; + if (format >= VDO_COL_FMT_ARGB) { + scl_regs1->r_ctl.b.rgb_mode = + (format == VDO_COL_FMT_RGB_565) ? 0x1 : 0x3; + if (format == VDO_COL_FMT_ABGR) + p_scl->abgr_mode = 1; + return; + } + scl_regs1->r_ctl.b.rgb_mode = 0; + scl_regs1->r_ctl.b.rgb = 0x0; + switch (format) { + case VDO_COL_FMT_YUV444: + scl_regs1->r_ctl.b.yuv = 0x2; + break; + case VDO_COL_FMT_YUV422H: + scl_regs1->r_ctl.b.yuv = 0x0; + break; + case VDO_COL_FMT_YUV420: + scl_regs1->r_ctl.b.yuv = 0x1; + break; + default: + DBG_ERR("color fmt %d\n", format); + return; + } +} + +vdo_color_fmt sclr_get_color_format(void) +{ + switch (scl_regs1->r_ctl.b.rgb_mode) { + case 0x1: + return VDO_COL_FMT_RGB_565; + case 0x3: + return VDO_COL_FMT_ARGB; + default: + break; + } + switch (scl_regs1->r_ctl.b.yuv) { + case 0: + return VDO_COL_FMT_YUV422H; + case 1: + return VDO_COL_FMT_YUV420; + case 2: + return VDO_COL_FMT_YUV444; + default: + break; + } + return VDO_COL_FMT_YUV444; +} + +void sclr_set_media_format(vpp_media_format_t format) +{ + scl_regs1->r_ctl.b.h264 = (format == VPP_MEDIA_FMT_H264) ? 1 : 0; +} + +void sclr_set_fb_addr(U32 y_addr, U32 c_addr) +{ + unsigned int line_y, line_c; + unsigned int offset_y, offset_c; + unsigned int pre_y, pre_c; + + DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", y_addr, c_addr); + + offset_y = offset_c = 0; + line_y = line_c = scl_regs1->r_h_size.b.fb_w; + switch (sclr_get_color_format()) { + case VDO_COL_FMT_YUV420: + offset_c /= 2; + line_c = 0; + break; + case VDO_COL_FMT_YUV422H: + break; + case VDO_COL_FMT_ARGB: + offset_y *= 4; + line_y *= 4; + break; + case VDO_COL_FMT_RGB_565: + offset_y *= 2; + line_y *= 2; + break; + default: + offset_c *= 2; + line_c *= 2; + break; + } + pre_y = scl_regs1->r_ysa; + pre_c = scl_regs1->r_csa; + scl_regs1->r_ysa = y_addr + offset_y; + scl_regs1->r_csa = c_addr + offset_c; +} + +void sclr_get_fb_addr(U32 *y_addr, U32 *c_addr) +{ + *y_addr = scl_regs1->r_ysa; + *c_addr = scl_regs1->r_csa; +/* DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", *y_addr, *c_addr); */ +} + +void sclr_set_width(U32 y_pixel, U32 y_buffer) +{ + scl_regs1->r_h_size.b.pix_w = y_pixel; + scl_regs1->r_h_size.b.fb_w = y_buffer; +} + +void sclr_get_width(U32 *p_y_pixel, U32 *p_y_buffer) +{ + *p_y_pixel = scl_regs1->r_h_size.b.pix_w; + *p_y_buffer = scl_regs1->r_h_size.b.fb_w; +} + +void sclr_set_crop(U32 h_crop, U32 v_crop) +{ + scl_regs1->r_crop.b.hcrop = h_crop; + scl_regs1->r_crop.b.vcrop = v_crop; +} + +void sclr_get_fb_info(U32 *width, U32 *act_width, + U32 *x_offset, U32 *y_offset) +{ + *width = scl_regs1->r_h_size.b.fb_w; + *act_width = scl_regs1->r_h_size.b.pix_w; + *x_offset = scl_regs1->r_crop.b.hcrop; + *y_offset = scl_regs1->r_crop.b.vcrop; +} + +void sclr_set_threshold(U32 value) +{ + scl_regs1->r_fifo_ctl.b.thr = value; +} + +void sclw_set_mif_enable(vpp_flag_t enable) +{ + scl_regs1->w_ctl.b.mif_enable = enable; +} + +void sclw_set_color_format(vdo_color_fmt format) +{ + /* 0-888(4 byte), 1-5515(2 byte), 2-666(4 byte), 3-565(2 byte) */ + switch (format) { + case VDO_COL_FMT_RGB_666: + scl_regs1->w_ctl.b.rgb = 1; + scl_regs2->igs.b.mode = 2; + break; + case VDO_COL_FMT_RGB_565: + scl_regs1->w_ctl.b.rgb = 1; + scl_regs2->igs.b.mode = 3; + break; + case VDO_COL_FMT_RGB_1555: + scl_regs1->w_ctl.b.rgb = 1; + scl_regs2->igs.b.mode = 1; + break; + case VDO_COL_FMT_ARGB: + scl_regs1->w_ctl.b.rgb = 1; + scl_regs2->igs.b.mode = 0; + break; + case VDO_COL_FMT_YUV444: + scl_regs1->w_ctl.b.rgb = 0; + scl_regs1->w_ctl.b.yuv = 0; + scl_regs2->igs.b.mode = 0; + break; + case VDO_COL_FMT_YUV422H: + case VDO_COL_FMT_YUV420: + scl_regs1->w_ctl.b.rgb = 0; + scl_regs1->w_ctl.b.yuv = 1; + scl_regs2->igs.b.mode = 0; + break; + default: + DBGMSG("*E* check the parameter.\n"); + return; + } +} + +vdo_color_fmt sclw_get_color_format(void) +{ + if (scl_regs1->w_ctl.b.rgb) { + switch (scl_regs2->igs.b.mode) { + case 0: + return VDO_COL_FMT_ARGB; + case 1: + return VDO_COL_FMT_RGB_1555; + case 2: + return VDO_COL_FMT_RGB_666; + case 3: + return VDO_COL_FMT_RGB_565; + } + } + + if (scl_regs1->w_ctl.b.yuv) + return VDO_COL_FMT_YUV422H; + return VDO_COL_FMT_YUV444; +} + +void sclw_set_alpha(int enable, char data) +{ + scl_regs2->argb_alpha.b.data = data; + scl_regs2->argb_alpha.b.enable = enable; +} + +void sclw_set_field_mode(vpp_display_format_t fmt) +{ + scl_regs1->r_ctl.b.field = fmt; +} + +void sclw_set_fb_addr(U32 y_addr, U32 c_addr) +{ + DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", y_addr, c_addr); +/* if( (y_addr & 0x3f) || (c_addr & 0x3f) ){ + DPRINT("[SCL] *E* addr should align 64\n"); + } */ + scl_regs1->w_ysa = y_addr; + scl_regs1->w_csa = c_addr; +} + +void sclw_get_fb_addr(U32 *y_addr, U32 *c_addr) +{ + *y_addr = scl_regs1->w_ysa; + *c_addr = scl_regs1->w_csa; + DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", *y_addr, *c_addr); +} + +void sclw_set_fb_width(U32 width, U32 buf_width) +{ + scl_regs1->w_y_time.b.pxl_w = width; + scl_regs1->w_y_time.b.fb_w = buf_width; + if (sclw_get_color_format() == VDO_COL_FMT_YUV444) { + scl_regs1->w_c_time.b.pxl_w = width; + scl_regs1->w_c_time.b.fb_w = buf_width * 2; + } else { + scl_regs1->w_c_time.b.pxl_w = width / 2; + scl_regs1->w_c_time.b.fb_w = buf_width; + } +} + +void sclw_get_fb_width(U32 *width, U32 *buf_width) +{ + *width = scl_regs1->w_y_time.b.pxl_w; + *buf_width = scl_regs1->w_y_time.b.fb_w; +} + +void scl_R2_set_mif_enable(int enable) +{ + scl_regs1->r2_ctl.b.mif_en = enable; +} + +void scl_R2_set_colorbar(int enable, int wide, int inv) +{ + scl_regs1->r2_ctl.b.color_en = enable; + scl_regs1->r2_ctl.b.color_wide = wide; + scl_regs1->r2_ctl.b.color_inv = inv; +} + +void scl_R2_set_color_format(vdo_color_fmt colfmt) +{ + if (colfmt >= VDO_COL_FMT_ARGB) { + scl_regs1->r2_ctl.b.rgb_mode = + (colfmt == VDO_COL_FMT_RGB_565) ? 0x1 : 0x3; + return; + } + scl_regs1->r2_ctl.b.rgb_mode = 0; + switch (colfmt) { + case VDO_COL_FMT_YUV444: + scl_regs1->r2_ctl.b.vfmt = 0x2; + break; + case VDO_COL_FMT_YUV422H: + scl_regs1->r2_ctl.b.vfmt = 0x0; + break; + case VDO_COL_FMT_YUV420: + scl_regs1->r2_ctl.b.vfmt = 0x1; + break; + default: + DBG_ERR("color fmt %d\n", colfmt); + return; + } +} + +vdo_color_fmt scl_R2_get_color_format(void) +{ + switch (scl_regs1->r2_ctl.b.rgb_mode) { + case 0: + switch (scl_regs1->r2_ctl.b.vfmt) { + case 0: + return VDO_COL_FMT_YUV422H; + case 1: + return VDO_COL_FMT_YUV420; + case 2: + default: + return VDO_COL_FMT_YUV444; + } + break; + case 1: + return VDO_COL_FMT_RGB_565; + case 3: + default: + break; + } + return VDO_COL_FMT_ARGB; +} + +void scl_R2_set_csc_mode(vpp_csc_t mode) +{ + vdo_color_fmt src_fmt, dst_fmt; + + src_fmt = scl_R2_get_color_format(); + dst_fmt = sclw_get_color_format(); + mode = vpp_check_csc_mode(mode, src_fmt, dst_fmt, 0); + + scl_regs2->r2_csc1 = vpp_csc_parm[mode][0]; + scl_regs2->r2_csc2 = vpp_csc_parm[mode][1]; + scl_regs2->r2_csc3 = vpp_csc_parm[mode][2]; + scl_regs2->r2_csc4 = vpp_csc_parm[mode][3]; + scl_regs2->r2_csc5 = vpp_csc_parm[mode][4]; + scl_regs2->r2_csc6 = vpp_csc_parm[mode][5]; + scl_regs2->r2_csc.val = vpp_csc_parm[mode][6]; + scl_regs2->r2_csc.b.enable = (mode >= VPP_CSC_MAX) ? 0 : 1; +} + +void scl_R2_set_framebuffer(vdo_framebuf_t *fb) +{ + scl_regs1->r2_ctl.b.iofmt = (fb->flag & VDO_FLAG_INTERLACE) ? 1 : 0; + scl_R2_set_color_format(fb->col_fmt); + scl_regs1->r2_ysa = fb->y_addr; + scl_regs1->r2_csa = fb->c_addr; + scl_regs1->r2_h_size.b.fbw = fb->fb_w; + scl_regs1->r2_h_size.b.lnsize = fb->img_w; + scl_regs1->r2_crop.b.hcrop = fb->h_crop; + scl_regs1->r2_crop.b.vcrop = fb->v_crop; + scl_R2_set_csc_mode(p_scl->fb_p->csc_mode); +} + +void scl_ALPHA_set_enable(int enable) +{ + scl_regs1->alpha_colorkey.b.enable = enable; +} + +void scl_ALPHA_set_swap(int enable) +{ + /* 0-(alpha,1-alpha),1:(1-alpha,alpha) */ + scl_regs1->alpha_md.b.swap = enable; +} + +void scl_ALPHA_set_src(int mode, int fixed) +{ + /* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */ + scl_regs1->alpha_md.b.src = mode; + scl_regs1->alpha_fxd.b.src_fixed = fixed; +} + +void scl_ALPHA_set_dst(int mode, int fixed) +{ + /* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */ + scl_regs1->alpha_md.b.dst = mode; + scl_regs1->alpha_fxd.b.dst_fixed = fixed; +} + +void scl_ALPHA_set_color_key(int rmif2, int comp, int mode, int colkey) +{ + /* 0-RMIF1,1-RMIF2 */ + scl_regs1->alpha_colorkey.b.from = rmif2; + /* 0-888,1-777,2-666,3-555 */ + scl_regs1->alpha_colorkey.b.comp = comp; + /* (Non-Hit,Hit):0/1-(alpha,alpha), + 2-(alpha,pix1),3-(pix1,alpha),4-(alpha,pix2), + 5-(pix2,alpha),6-(pix1,pix2),7-(pix2,pix1) */ + scl_regs1->alpha_colorkey.b.mode = mode; + scl_regs1->alpha_colorkey_rgb.val = colkey; +} + +void scl_set_overlap(vpp_overlap_t *p) +{ +#if 0 + DPRINT("alpha src %d,0x%x,dst %d,0x%x\n", + p->alpha_src_type, p->alpha_src, + p->alpha_dst_type, p->alpha_dst); + DPRINT("colkey from %d,comp %d,mode %d,0x%x\n", + p->color_key_from, p->color_key_comp, + p->color_key_mode, p->color_key); +#endif + scl_ALPHA_set_src(p->alpha_src_type, p->alpha_src); + scl_ALPHA_set_dst(p->alpha_dst_type, p->alpha_dst); + scl_ALPHA_set_swap(p->alpha_swap); + scl_ALPHA_set_color_key(p->color_key_from, p->color_key_comp, + p->color_key_mode, p->color_key); +} + +void scl_set_req_num(int ynum, int cnum) +{ + scl_regs1->r_req_num.b.y_req_num = ynum; + scl_regs1->r_req_num.b.c_req_num = cnum; +} + +static void scl_set_scale_PP(unsigned int src, unsigned int dst, + int horizontal) +{ + int gcd; + +/* DBGMSG("scale PP(s %d,d %d,is H %d)\n",src,dst,horizontal); */ + + /* gcd = scl_get_gcd(src,dst); */ + gcd = 1; + src /= gcd; + dst /= gcd; + + if (horizontal) + scl_set_H_scale(dst, src); + else + scl_set_V_scale(dst, src); +} + +void scl_set_scale(unsigned int SRC_W, unsigned int SRC_H, + unsigned int DST_W, unsigned int DST_H) +{ + int h_scale_up; + int v_scale_up; + + DBGMSG("[SCL] src(%dx%d),dst(%dx%d)\n", SRC_W, SRC_H, DST_W, DST_H); + + h_scale_up = (DST_W > SRC_W) ? 1 : 0; + v_scale_up = (DST_H > SRC_H) ? 1 : 0; + + if (((DST_W / SRC_W) >= 32) || ((DST_W / SRC_W) < 1/32)) + DBGMSG("*W* SCL H scale rate invalid\n"); + + if (((DST_H / SRC_H) >= 32) || ((DST_H / SRC_H) < 1/32)) + DBGMSG("*W* SCL V scale rate invalid\n"); + +/* DBGMSG("scale H %d,V %d\n",h_scale_up,v_scale_up); */ + + sclr_set_mif2_enable(VPP_FLAG_DISABLE); + scl_set_scale_PP(SRC_W, DST_W, 1); + scl_set_scale_PP(SRC_H, DST_H, 0); + scl_set_scale_enable(v_scale_up, h_scale_up); + + { + int rec_h, rec_v; + int h, v; + + h = rec_h = 0; + if (SRC_W > DST_W) { /* scale down */ + switch (p_scl->scale_mode) { + case VPP_SCALE_MODE_ADAPTIVE: + if ((DST_W * 2) > SRC_W) /* 1 > mode(3) > 1/2 */ + h = 1; /* bilinear mode */ + else + rec_h = 1; /* recursive mode */ + break; + case VPP_SCALE_MODE_BILINEAR: + h = 1; /* bilinear mode */ + break; + case VPP_SCALE_MODE_RECURSIVE: + rec_h = 1; /* recursive mode */ + break; + default: + break; + } + } + + v = rec_v = 0; + if (SRC_H > DST_H) { /* scale down */ + switch (p_scl->scale_mode) { + case VPP_SCALE_MODE_ADAPTIVE: + if ((DST_H * 2) > SRC_H) /* 1 > mode(3) > 1/2 */ + v = 1; /* bilinear mode */ + else + rec_v = 1; /* recursive mode */ + break; + case VPP_SCALE_MODE_BILINEAR: + v = 1; /* bilinear mode */ + break; + case VPP_SCALE_MODE_RECURSIVE: + rec_v = 1; /* recursive mode */ + break; + default: + break; + } + } + + if (SRC_W == DST_W) + rec_h = 1; + if (SRC_H == DST_H) + rec_v = 1; + scl_regs1->true_bilinear.b.h = h; + scl_regs1->true_bilinear.b.v = v; + scl_regs2->recursive_mode.b.h = rec_h; + scl_regs2->recursive_mode.b.v = rec_v; + if (v) { + scl_regs1->vxwidth.b.vxwidth = + scl_regs1->vxwidth.b.vxwidth - 1; + scl_regs1->vxwidth.b.dst_vxwidth = + scl_regs1->vxwidth.b.vxwidth; + } + sclr_set_mif2_enable((v) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE); + } +} + +void sclr_set_framebuffer(vdo_framebuf_t *inbuf) +{ + sclr_set_color_format(inbuf->col_fmt); + sclr_set_crop(inbuf->h_crop, inbuf->v_crop); + sclr_set_width(inbuf->img_w, inbuf->fb_w); + sclr_set_fb_addr(inbuf->y_addr, inbuf->c_addr); + sclr_set_field_mode(vpp_get_fb_field(inbuf)); +} + +void scl_set_scale_timing(vdo_framebuf_t *s, vdo_framebuf_t *d) +{ + vpp_clock_t timing; + unsigned int pixel_clock; + + /* scl TG */ + timing.total_pixel_of_line = (d->img_w > s->img_w) ? + d->img_w : s->img_w; + timing.total_line_of_frame = (d->img_h > s->img_h) ? + d->img_h : s->img_h; + timing.begin_pixel_of_active = 60; + timing.end_pixel_of_active = timing.total_pixel_of_line + 60; + timing.total_pixel_of_line = timing.total_pixel_of_line + 120; + timing.begin_line_of_active = 8; + timing.end_line_of_active = timing.total_line_of_frame + 8; + timing.total_line_of_frame = timing.total_line_of_frame + 16; + timing.line_number_between_VBIS_VBIE = 4; + timing.line_number_between_PVBI_VBIS = 1; + pixel_clock = timing.total_pixel_of_line * + timing.total_line_of_frame * p_scl->fb_p->framerate; + scl_set_timing(&timing, pixel_clock); +} + +void sclw_set_framebuffer(vdo_framebuf_t *fb) +{ + unsigned int yaddr, caddr; + int y_bpp, c_bpp; + + vpp_get_colfmt_bpp(fb->col_fmt, &y_bpp, &c_bpp); + yaddr = fb->y_addr + ((fb->fb_w * fb->v_crop + fb->h_crop) * y_bpp / 8); + caddr = (c_bpp) ? (fb->c_addr + (((fb->fb_w * fb->v_crop + + fb->h_crop) / 2) * 2 * c_bpp / 8)) : 0; + sclw_set_fb_addr(yaddr, caddr); + sclw_set_color_format(fb->col_fmt); + sclw_set_fb_width(fb->img_w, fb->fb_w); + sclw_set_field_mode(vpp_get_fb_field(fb)); + scl_set_csc_mode(p_scl->fb_p->csc_mode); +} + +void scl_init(void *base) +{ + struct scl_mod_t *mod_p; + struct vpp_fb_base_t *fb_p; + + mod_p = (struct scl_mod_t *) base; + fb_p = mod_p->fb_p; + + scl_set_reg_level(VPP_REG_LEVEL_1); + scl_set_tg_enable(VPP_FLAG_DISABLE); + scl_set_enable(VPP_FLAG_DISABLE); + scl_set_int_enable(VPP_FLAG_DISABLE, VPP_INT_ALL); + sclr_set_mif_enable(VPP_FLAG_DISABLE); + sclr_set_mif2_enable(VPP_FLAG_DISABLE); + sclr_set_colorbar(VPP_FLAG_DISABLE, 0, 0); + + scl_set_int_enable(VPP_FLAG_ENABLE, mod_p->int_catch); + scl_set_watchdog(fb_p->wait_ready); + scl_set_csc_mode(fb_p->csc_mode); + sclr_set_media_format(fb_p->media_fmt); + sclr_set_threshold(0xf); + + /* filter default value */ + scl_regs2->dblk_threshold.b.layer1_boundary = 48; + scl_regs2->dblk_threshold.b.layer2_boundary = 16; + + scl_regs2->field_flicker.b.y_thd = 8; + scl_regs2->field_flicker.b.c_thd = 8; + scl_regs2->field_flicker.b.condition = 0; + + scl_regs2->frame_flicker.b.rgb = 0; + scl_regs2->frame_flicker.b.sampler = 14; + scl_regs2->frame_flicker.b.scene_chg_thd = 32; + scl_set_reg_update(VPP_FLAG_ENABLE); + scl_set_tg_enable(VPP_FLAG_DISABLE); +} + +void sclw_init(void *base) +{ + sclw_set_mif_enable(VPP_FLAG_DISABLE); + sclw_set_fb_width(VPP_HD_DISP_RESX, VPP_HD_MAX_RESX); +/* vppif_reg32_write(SCL_SCLDW_METHOD,0x1); */ /* drop line enable */ +} + +#ifdef __KERNEL__ +/* static struct work_struct scl_proc_scale_wq; */ +DECLARE_WAIT_QUEUE_HEAD(scl_proc_scale_event); +static void scl_proc_scale_complete_work(struct work_struct *work) +#else +static void scl_proc_scale_complete_work(int arg) +#endif +{ +/* DPRINT("[SCL] scl_proc_scale_complete_work\n"); */ + p_scl->scale_complete = 1; +#ifdef __KERNEL__ + wake_up_interruptible(&scl_proc_scale_event); +#endif +#if 0 /* avoid mutex in irq */ + vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 0); +#endif +} + +#ifdef __KERNEL__ +struct timer_list scl_scale_timer; +#endif +int scl_proc_scale_complete(void *arg) +{ +#ifdef __KERNEL__ + del_timer(&scl_scale_timer); +#endif +/* DPRINT("[SCL] scl_proc_scale_complete\n"); */ + if (scl_regs1->tg_sts.b.tgerr) { + DPRINT("[SCL] scale TG err 0x%x,0x%x\n", + scl_regs1->tg_sts.val, scl_regs1->w_ff_ctl.val); + scl_regs1->tg_sts.val = BIT0; + scl_regs1->w_ff_ctl.val = 0x10101; + } + scl_set_tg_enable(VPP_FLAG_DISABLE); +#ifndef CONFIG_UBOOT + vppm_set_int_enable(VPP_FLAG_DISABLE, SCL_COMPLETE_INT); +#endif + sclw_set_mif_enable(VPP_FLAG_DISABLE); + sclr_set_mif_enable(VPP_FLAG_DISABLE); + sclr_set_mif2_enable(VPP_FLAG_DISABLE); + scl_set_enable(VPP_FLAG_DISABLE); + +/* #ifdef __KERNEL__ */ +#if 0 + INIT_WORK(&scl_proc_scale_wq, scl_proc_scale_complete_work); + schedule_work(&scl_proc_scale_wq); +#else + scl_proc_scale_complete_work(0); +#endif + return 0; +} + +void scl_scale_timeout(int arg) +{ + DBG_ERR("scale timeout\n"); +#if 0 + scl_reg_dump(); + g_vpp.dbg_msg_level = VPP_DBGLVL_STREAM; + g_vpp.dbg_cnt = 1000; +#endif + scl_proc_scale_complete(0); +} + +void scl_set_scale_timer(int ms) +{ +#ifdef __KERNEL__ + if (scl_scale_timer.function) + del_timer(&scl_scale_timer); + init_timer(&scl_scale_timer); + scl_scale_timer.function = (void *) scl_scale_timeout; + scl_scale_timer.expires = jiffies + msecs_to_jiffies(ms); + add_timer(&scl_scale_timer); +#endif +} + +int scl_proc_scale_finish(void) +{ + int ret = 0; + +#ifdef __KERNEL__ + +/* DPRINT("[SCL] scl_proc_scale_finish\n"); */ + ret = wait_event_interruptible_timeout(scl_proc_scale_event, + (p_scl->scale_complete != 0), 3 * HZ); + if (ret == 0) { /* timeout */ + DPRINT("[SCL] *E* wait scale timeout\n"); + ret = -1; + } else { + ret = 0; + } +#endif +#if 1 /* avoid mutex in irq */ + vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 0); +#endif + return ret; +} + +void scl_check_framebuf(vdo_framebuf_t *s, + vdo_framebuf_t *in, vdo_framebuf_t *out) +{ + if (s) { + if (s->img_w > WMT_SCL_H_DIV_MAX) + DBG_ERR("src w %d over %d\n", + s->img_w, WMT_SCL_H_DIV_MAX); + if (s->img_h > WMT_SCL_V_DIV_MAX) + DBG_ERR("src h %d over %d\n", + s->img_h, WMT_SCL_V_DIV_MAX); + if (s->col_fmt >= VDO_COL_FMT_ARGB) { + if (s->y_addr % 4) + DBG_ERR("src addr 0x%x not align 4\n", + s->y_addr); + } + if (s->fb_w > WMT_SCL_H_DIV_MAX) + DBG_ERR("src fb w %d over %d\n", + s->fb_w, WMT_SCL_H_DIV_MAX); + if (s->y_addr % 64) + DBG_ERR("src fb addr 0x%x no align 64\n", s->y_addr); + } else { + DBG_ERR("src null\n"); + } + + if (in) { + if (in->img_w > WMT_SCL_H_DIV_MAX) + DBG_ERR("in w %d over %d\n", + in->img_w, WMT_SCL_H_DIV_MAX); + if (in->img_h > WMT_SCL_V_DIV_MAX) + DBG_ERR("in h %d over %d\n", + in->img_h, WMT_SCL_V_DIV_MAX); + if (in->col_fmt >= VDO_COL_FMT_ARGB) { + if (in->y_addr % 4) + DBG_ERR("in addr 0x%x not align 4\n", + in->y_addr); + } + if (in->fb_w > WMT_SCL_H_DIV_MAX) + DBG_ERR("in fb w %d over %d\n", + in->fb_w, WMT_SCL_H_DIV_MAX); + if (in->y_addr % 64) + DBG_ERR("in fb addr 0x%x no align 64\n", in->y_addr); + } + + if (out) { + if (s && (s->img_w == out->img_w)) { + if (out->img_w > WMT_SCL_H_DIV_MAX) + DBG_ERR("out w %d over %d\n", out->img_w, + WMT_SCL_H_DIV_MAX); + } else { + if (out->img_w > WMT_SCL_SCALE_DST_H_MAX) + DBG_ERR("out w %d over %d\n", out->img_w, + WMT_SCL_SCALE_DST_H_MAX); + + } + if (out->col_fmt >= VDO_COL_FMT_ARGB) { + if (out->y_addr % 4) + DBG_ERR("out addr 0x%x not align 4\n", + out->y_addr); + } + if (out->fb_w > WMT_SCL_H_DIV_MAX) + DBG_ERR("out fb w %d over %d\n", + out->fb_w, WMT_SCL_H_DIV_MAX); + if (out->y_addr % 64) + DBG_ERR("out fb addr 0x%x no align 64\n", out->y_addr); + } else { + DBG_ERR("out null\n"); + } +} + +#define CONFIG_VPP_CHECK_SCL_STATUS +int scl_set_scale_overlap(vdo_framebuf_t *s, + vdo_framebuf_t *in, vdo_framebuf_t *out) +{ + int ret = 0; + + if (vpp_check_dbg_level(VPP_DBGLVL_SCALE)) { + scl_check_framebuf(s, in, out); + + if (s) + vpp_show_framebuf("src1", s); + if (in) + vpp_show_framebuf("src2", in); + if (out) + vpp_show_framebuf("dst", out); + } + + if (p_scl->scale_sync) + vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_ENABLE, 0); + + scl_set_timing_master(VPP_MOD_SCL); + + if (s) { + p_scl->fb_p->fb = *s; + sclr_set_framebuffer(s); + sclr_set_mif_enable(VPP_FLAG_ENABLE); + } else { + DPRINT("[SCL] *E* no source\n"); + return -1; + } + + if (in && (in->y_addr == 0)) + in = 0; + + scl_ALPHA_set_enable((in) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE); + scl_R2_set_mif_enable((in) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE); + if (in) + scl_R2_set_framebuffer(in); + if (out) { + p_sclw->fb_p->fb = *out; + sclw_set_framebuffer(out); + } else { + DPRINT("[SCL] *E* no dest\n"); + return -1; + } + + scl_set_scale(s->img_w, s->img_h, out->img_w, out->img_h); + scl_set_scale_timing(s, out); + + /* scale process */ + scl_set_enable(VPP_FLAG_ENABLE); + scl_regs1->tg_ctl.b.oneshot = 1; + sclw_set_mif_enable(VPP_FLAG_ENABLE); + scl_set_tg_enable(VPP_FLAG_ENABLE); +#ifdef CONFIG_VPP_CHECK_SCL_STATUS + scl_regs1->tg_sts.val = BIT0; + scl_regs1->w_ff_ctl.val = 0x10101; +#endif + p_scl->scale_complete = 0; +#ifndef CONFIG_UBOOT + vppm_set_int_enable(VPP_FLAG_ENABLE, SCL_COMPLETE_INT); +#endif +#if 0 /* for debug scale */ + scl_reg_dump(); +#endif +#ifdef CONFIG_UBOOT + while (scl_regs1->tg_ctl.b.enable); + scl_proc_scale_complete(0); + scl_proc_scale_finish(); +#else + if (p_scl->scale_sync) { + ret = vpp_irqproc_work(SCL_COMPLETE_INT, + (void *)scl_proc_scale_complete, 0, 100, 1); + scl_proc_scale_finish(); + } else { + vpp_irqproc_work(SCL_COMPLETE_INT, + (void *)scl_proc_scale_complete, 0, 0, 1); + scl_set_scale_timer(100); + } +#endif + return ret; +} + +int scl_proc_scale(vdo_framebuf_t *src_fb, vdo_framebuf_t *dst_fb) +{ + int ret = 0; + + if (dst_fb->col_fmt == VDO_COL_FMT_YUV420) { + int size; + unsigned int buf; + vdo_framebuf_t dfb; + + dfb = *dst_fb; /* backup dst fb */ + + /* alloc memory */ + size = dst_fb->img_w * dst_fb->img_h + 64; + buf = (unsigned int) kmalloc(size, GFP_KERNEL); + if (!buf) { + DPRINT("[SCL] *E* malloc fail %d\n", size); + return -1; + } + + if (buf % 64) + buf = buf + (64 - (buf % 64)); + + /* scale for Y */ + dst_fb->c_addr = buf; + ret = scl_set_scale_overlap(src_fb, 0, dst_fb); + if (ret == 0) { + /* V 1/2 scale for C */ + dst_fb->y_addr = buf; + dst_fb->c_addr = dfb.c_addr; + dst_fb->img_h = dfb.img_h / 2; + ret = scl_set_scale_overlap(src_fb, 0, dst_fb); + } + kfree((void *)buf); + *dst_fb = dfb; /* restore dst fb */ + } else { + ret = scl_set_scale_overlap(src_fb, 0, dst_fb); + } + return ret; +} + +#ifdef CONFIG_PM +static unsigned int *scl_pm_bk2; +static unsigned int scl_pm_enable, scl_pm_tg; +static unsigned int scl_pm_r_mif1, scl_pm_r_mif2, scl_pm_w_mif; +void scl_suspend(int sts) +{ + switch (sts) { + case 0: /* disable module */ + vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_ENABLE, 1); + scl_pm_enable = scl_regs1->en.b.alu_enable; + scl_regs1->en.b.alu_enable = 0; + scl_pm_r_mif1 = scl_regs1->r_ctl.b.mif_enable; + scl_pm_r_mif2 = scl_regs1->r2_ctl.b.mif_en; + scl_regs1->r2_ctl.b.mif_en = 0; + scl_regs1->r_ctl.b.mif_enable = 0; + scl_pm_w_mif = scl_regs1->w_ctl.b.mif_enable; + scl_regs1->w_ctl.b.mif_enable = 0; + break; + case 1: /* disable tg */ + scl_pm_tg = scl_regs1->tg_ctl.b.enable; + scl_regs1->tg_ctl.b.enable = 0; + break; + case 2: /* backup register */ + p_scl->reg_bk = vpp_backup_reg(REG_SCL_BASE1_BEGIN, + (REG_SCL_BASE1_END - REG_SCL_BASE1_BEGIN)); + scl_pm_bk2 = vpp_backup_reg(REG_SCL_BASE2_BEGIN, + (REG_SCL_BASE2_END - REG_SCL_BASE2_BEGIN)); + break; + default: + break; + } +} + +void scl_resume(int sts) +{ + switch (sts) { + case 0: /* restore register */ + vpp_restore_reg(REG_SCL_BASE1_BEGIN, + (REG_SCL_BASE1_END - REG_SCL_BASE1_BEGIN), + p_scl->reg_bk); + vpp_restore_reg(REG_SCL_BASE2_BEGIN, + (REG_SCL_BASE2_END - REG_SCL_BASE2_BEGIN), scl_pm_bk2); + p_scl->reg_bk = 0; + scl_pm_bk2 = 0; + break; + case 1: /* enable module */ + scl_regs1->w_ctl.b.mif_enable = scl_pm_w_mif; + scl_regs1->r_ctl.b.mif_enable = scl_pm_r_mif1; + scl_regs1->r2_ctl.b.mif_en = scl_pm_r_mif2; + scl_regs1->en.b.alu_enable = scl_pm_enable; + break; + case 2: /* enable tg */ + scl_regs1->tg_ctl.b.enable = scl_pm_tg; + vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 1); + break; + default: + break; + } +} +#else +#define scl_suspend NULL +#define scl_resume NULL +#endif + +int scl_mod_init(void) +{ + struct vpp_fb_base_t *mod_fb_p; + vdo_framebuf_t *fb_p; + + /* -------------------- SCL module -------------------- */ + { + struct scl_mod_t *scl_mod_p; + + scl_mod_p = (struct scl_mod_t *) vpp_mod_register(VPP_MOD_SCL, + sizeof(struct scl_mod_t), + VPP_MOD_FLAG_FRAMEBUF); + if (!scl_mod_p) { + DPRINT("*E* SCL module register fail\n"); + return -1; + } + + /* module member variable */ + scl_mod_p->int_catch = VPP_INT_NULL; + scl_mod_p->scale_mode = VPP_SCALE_MODE_ADAPTIVE; + scl_mod_p->pm = DEV_SCL444U; + scl_mod_p->filter_mode = VPP_FILTER_SCALE; + + /* module member function */ + scl_mod_p->init = scl_init; + scl_mod_p->set_enable = scl_set_enable; + scl_mod_p->set_colorbar = sclr_set_colorbar; + scl_mod_p->dump_reg = scl_reg_dump; + scl_mod_p->get_sts = scl_get_int_status; + scl_mod_p->clr_sts = scl_clean_int_status; + scl_mod_p->scale = scl_proc_scale; + scl_mod_p->scale_finish = scl_proc_scale_finish; + scl_mod_p->suspend = scl_suspend; + scl_mod_p->resume = scl_resume; + + /* module frame buffer variable */ + mod_fb_p = scl_mod_p->fb_p; + fb_p = &mod_fb_p->fb; + + fb_p->y_addr = 0; + fb_p->c_addr = 0; + fb_p->col_fmt = VDO_COL_FMT_YUV422H; + fb_p->img_w = VPP_HD_DISP_RESX; + fb_p->img_h = VPP_HD_DISP_RESY; + fb_p->fb_w = VPP_HD_MAX_RESX; + fb_p->fb_h = VPP_HD_MAX_RESY; + fb_p->h_crop = 0; + fb_p->v_crop = 0; + + /* module frame buffer member function */ + mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255; + mod_fb_p->set_framebuf = sclr_set_framebuffer; + mod_fb_p->set_addr = sclr_set_fb_addr; + mod_fb_p->get_addr = sclr_get_fb_addr; + mod_fb_p->set_csc = scl_set_csc_mode; + mod_fb_p->framerate = 0x7fffffff; + mod_fb_p->wait_ready = 0xffffffff; + mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420) + | BIT(VDO_COL_FMT_YUV422H) | BIT(VDO_COL_FMT_YUV444) + | BIT(VDO_COL_FMT_ARGB) | BIT(VDO_COL_FMT_RGB_565) + | VPP_FB_FLAG_CSC | VPP_FB_FLAG_FIELD; + p_scl = scl_mod_p; + p_scl->scale_complete = 1; + p_scl->scale_sync = 1; + } + + /* -------------------- SCLW module -------------------- */ + { + struct sclw_mod_t *sclw_mod_p; + + sclw_mod_p = (struct sclw_mod_t *) vpp_mod_register(VPP_MOD_SCLW, + sizeof(struct sclw_mod_t), + VPP_MOD_FLAG_FRAMEBUF); + if (!sclw_mod_p) { + DPRINT("*E* SCLW module register fail\n"); + return -1; + } + + /* module member variable */ + sclw_mod_p->int_catch = VPP_INT_NULL; + + /* module member function */ + sclw_mod_p->init = sclw_init; + sclw_mod_p->set_enable = sclw_set_mif_enable; + + /* module frame buffer */ + mod_fb_p = sclw_mod_p->fb_p; + fb_p = &mod_fb_p->fb; + + fb_p->y_addr = 0; + fb_p->c_addr = 0; + fb_p->col_fmt = VDO_COL_FMT_YUV422H; + fb_p->img_w = VPP_HD_DISP_RESX; + fb_p->img_h = VPP_HD_DISP_RESY; + fb_p->fb_w = VPP_HD_MAX_RESX; + fb_p->fb_h = VPP_HD_MAX_RESY; + fb_p->h_crop = 0; + fb_p->v_crop = 0; + + /* module frame buffer member function */ + mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255; + mod_fb_p->set_framebuf = sclw_set_framebuffer; + mod_fb_p->set_addr = sclw_set_fb_addr; + mod_fb_p->get_addr = sclw_get_fb_addr; + mod_fb_p->set_csc = scl_set_csc_mode; + mod_fb_p->wait_ready = 0xffffffff; + mod_fb_p->capability = BIT(VDO_COL_FMT_YUV422H) + | BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB) + | BIT(VDO_COL_FMT_RGB_565) | VPP_FB_FLAG_CSC + | BIT(VDO_COL_FMT_YUV420); + p_sclw = sclw_mod_p; + } + return 0; +} +module_init(scl_mod_init); +#endif /* WMT_FTBLK_SCL */ diff --git a/common/wmt_display/scl.h b/common/wmt_display/scl.h new file mode 100755 index 0000000..2d11b48 --- /dev/null +++ b/common/wmt_display/scl.h @@ -0,0 +1,128 @@ +/*++ + * linux/drivers/video/wmt/scl.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include "vpp.h" + +#ifndef SCL_H +#define SCL_H + +#define SCL_COMPLETE_INT VPP_INT_SCL_PVBI + +struct scl_mod_t { + VPP_MOD_BASE; + + int (*scale)(vdo_framebuf_t *src, vdo_framebuf_t *dst); + int (*scale_finish)(void); + + enum vpp_scale_mode_t scale_mode; + enum vpp_scale_mode_t scale_sync; + int scale_complete; + enum vpp_filter_mode_t filter_mode; + int abgr_mode; + + struct vpp_dbg_timer_t overlap_timer; + struct vpp_dbg_timer_t scale_timer; +}; + +struct sclw_mod_t { + VPP_MOD_BASE; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef SCL_C +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN struct scl_mod_t *p_scl; +EXTERN struct sclw_mod_t *p_sclw; + +#ifdef WMT_FTBLK_SCL + +EXTERN void scl_reg_dump(void); +EXTERN void sclr_set_framebuffer(vdo_framebuf_t *inbuf); +EXTERN void sclw_set_framebuffer(vdo_framebuf_t *outbuf); + +EXTERN void scl_set_enable(vpp_flag_t enable); +EXTERN void scl_set_reg_update(vpp_flag_t enable); +EXTERN void scl_set_reg_level(vpp_reglevel_t level); +EXTERN void scl_set_int_enable(vpp_flag_t enable, enum vpp_int_t int_bit); +EXTERN enum vpp_int_err_t scl_get_int_status(void); +EXTERN void scl_clean_int_status(enum vpp_int_err_t int_sts); +EXTERN void scl_set_csc_mode(vpp_csc_t mode); +EXTERN void scl_set_scale_enable(vpp_flag_t vscl_enable, + vpp_flag_t hscl_enable); +EXTERN void scl_set_V_scale(int A, int B); +EXTERN void scl_set_H_scale(int A, int B); +EXTERN void scl_set_crop(int offset_x, int offset_y); +EXTERN void scl_set_tg_enable(vpp_flag_t enable); +EXTERN void scl_set_timing_master(vpp_mod_t mod_bit); +EXTERN vpp_mod_t scl_get_timing_master(void); +EXTERN void scl_set_drop_line(vpp_flag_t enable); +EXTERN void sclr_get_fb_info(U32 *width, U32 *act_width, + U32 *x_offset, U32 *y_offset); +EXTERN void sclr_set_mif_enable(vpp_flag_t enable); +EXTERN void sclr_set_mif2_enable(vpp_flag_t enable); +EXTERN void sclr_set_colorbar(vpp_flag_t enable, int width, int inverse); +EXTERN void sclr_set_display_format(vpp_display_format_t source, + vpp_display_format_t target); +EXTERN void sclr_set_field_mode(vpp_display_format_t fmt); +EXTERN void sclr_set_color_format(vdo_color_fmt format); +EXTERN vdo_color_fmt sclr_get_color_format(void); +EXTERN void sclr_set_media_format(vpp_media_format_t format); +EXTERN void sclr_set_fb_addr(U32 y_addr, U32 c_addr); +EXTERN void sclr_get_fb_addr(U32 *y_addr, U32 *c_addr); +EXTERN void sclr_set_width(U32 y_pixel, U32 y_buffer); +EXTERN void sclr_get_width(U32 *p_y_pixel, U32 *p_y_buffer); +EXTERN void sclr_set_crop(U32 h_crop, U32 v_crop); +EXTERN void sclr_set_threshold(U32 value); +EXTERN vdo_color_fmt scl_R2_get_color_format(void); +EXTERN void sclw_set_mif_enable(vpp_flag_t enable); +EXTERN void sclw_set_color_format(vdo_color_fmt format); +EXTERN vdo_color_fmt sclw_get_color_format(void); +EXTERN void sclw_set_field_mode(vpp_display_format_t fmt); +EXTERN void sclw_set_fb_addr(U32 y_addr, U32 c_addr); +EXTERN void sclw_get_fb_addr(U32 *y_addr, U32 *c_addr); +EXTERN void sclw_set_fb_width(U32 y_pixel, U32 y_buffer); +EXTERN void sclw_get_fb_width(U32 *width, U32 *buf_width); +EXTERN void scl_set_scale(unsigned int SRC_W, unsigned int SRC_H, + unsigned int DST_W, unsigned int DST_H); +EXTERN int scl_mod_init(void); +EXTERN void scl_set_deblock_enable(int enable); +EXTERN void scl_set_field_filter_enable(int enable); +EXTERN void scl_set_frame_filter_enable(int enable); +EXTERN int scl_set_scale_overlap(vdo_framebuf_t *s, + vdo_framebuf_t *in, vdo_framebuf_t *out); +EXTERN void scl_set_overlap(vpp_overlap_t *p); +EXTERN int scl_mod_init(void); + +#ifdef __cplusplus +} +#endif +#endif /* WMT_FTBLK_SCL */ +#undef EXTERN +#endif /* SCL_H */ diff --git a/common/wmt_display/sw_i2c.c b/common/wmt_display/sw_i2c.c new file mode 100755 index 0000000..79acd96 --- /dev/null +++ b/common/wmt_display/sw_i2c.c @@ -0,0 +1,436 @@ +/*++ + * linux/drivers/video/wmt/sw_i2c.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include "vpp-osif.h" +#include "sw_i2c.h" + +#define SPEED 50 /* 5000000 */ + +#define delay_time 30 + +struct swi2c_reg_bk_t { + unsigned int gpio_en; + unsigned int out_en; + unsigned int data_out; + unsigned int pull_en; +}; + +#ifdef __KERNEL__ +static DEFINE_SPINLOCK(swi2c_irqlock); +unsigned long swi2c_irqlock_flags; +#endif +void wmt_swi2c_lock(int lock) +{ +#ifdef __KERNEL__ + if (lock) + spin_lock_irqsave(&swi2c_irqlock, swi2c_irqlock_flags); + else + spin_unlock_irqrestore(&swi2c_irqlock, swi2c_irqlock_flags); +#endif +} + +struct swi2c_reg_s *swi2c_scl, *swi2c_sda; + +void wmt_swi2c_delay(unsigned int time) +{ + udelay(time); +} + +void wmt_swi2c_SetSDAInput(void) +{ + outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask, swi2c_sda->gpio_en); + outw(inw(swi2c_sda->out_en) & ~swi2c_sda->bit_mask, swi2c_sda->out_en); +} + + +void wmt_swi2c_SetSDAOutput(void) +{ + outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask, swi2c_sda->gpio_en); + outw(inw(swi2c_sda->out_en) | swi2c_sda->bit_mask, swi2c_sda->out_en); +} + +bool wmt_swi2c_GetSDA(void) /* bit */ +{ + if (inw(swi2c_sda->data_in) & swi2c_sda->bit_mask) +#ifdef CFG_LOADER + return 1; + return 0; +#else + return (HW_REG bool) 1; + return (HW_REG bool) 0; +#endif +} + +bool wmt_swi2c_GetSCL(void) /* bit */ +{ + if (inw(swi2c_scl->data_in) & swi2c_scl->bit_mask) +#ifdef CFG_LOADER + return 1; + return 0; +#else + return (HW_REG bool) 1; + return (HW_REG bool) 0; +#endif +} + +void wmt_swi2c_SetSDA(int high) +{ + if (high) { + /* set to GPI and pull high */ + outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask, + swi2c_sda->gpio_en); + outw(inw(swi2c_sda->out_en) & ~swi2c_sda->bit_mask, + swi2c_sda->out_en); + if (swi2c_sda->pull_en) + outw(inw(swi2c_sda->pull_en) & + ~swi2c_sda->pull_en_bit_mask, + swi2c_sda->pull_en); + } else { + outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask, + swi2c_sda->gpio_en); + outw(inw(swi2c_sda->out_en) | swi2c_sda->bit_mask, + swi2c_sda->out_en); + outw(inw(swi2c_sda->data_out) & ~swi2c_sda->bit_mask, + swi2c_sda->data_out); + } +} + +void wmt_swi2c_SetSCL(int high) +{ + if (high) { + outw(inw(swi2c_scl->gpio_en) | swi2c_scl->bit_mask, + swi2c_scl->gpio_en); + outw(inw(swi2c_scl->out_en) & ~swi2c_scl->bit_mask, + swi2c_scl->out_en); + if (swi2c_scl->pull_en) + outw(inw(swi2c_scl->pull_en) & + ~swi2c_scl->pull_en_bit_mask, + swi2c_scl->pull_en); + } else { + outw(inw(swi2c_scl->gpio_en) | swi2c_scl->bit_mask, + swi2c_scl->gpio_en); + outw(inw(swi2c_scl->out_en) | swi2c_scl->bit_mask, + swi2c_scl->out_en); + outw(inw(swi2c_scl->data_out) & ~swi2c_scl->bit_mask, + swi2c_scl->data_out); + } +} + +int wmt_swi2c_SetData(int high) +{ + unsigned int wait = 1; + + wmt_swi2c_SetSDA(high); + do { + if (wmt_swi2c_GetSDA() == ((high) ? 1 : 0)) + return 0; + } while (wait++ < SPEED); + return 1; +} + +int wmt_swi2c_SetClock(int high) +{ + unsigned int wait = 1; + + udelay(5); /* 3-100kHz, 5-80kHz */ + + wmt_swi2c_SetSCL(high); + do { + if (wmt_swi2c_GetSCL() == ((high) ? 1 : 0)) + return 0; + } while (wait++ < SPEED); + return 1; /* fail */ +} + +int wmt_swi2c_StartI2C(void) +{ + if (wmt_swi2c_SetData(1)) + return 1; + if (wmt_swi2c_SetClock(1)) + return 2; + if (wmt_swi2c_SetData(0)) + return 3; + wmt_swi2c_delay(0); + if (wmt_swi2c_SetClock(0)) + return 4; + return 0; /* success */ +} + +int wmt_swi2c_StopI2C(void) +{ + if (wmt_swi2c_SetData(0)) + return 1; + if (wmt_swi2c_SetClock(0)) + return 1; + if (wmt_swi2c_SetClock(1)) + return 1; + wmt_swi2c_delay(0); + if (wmt_swi2c_SetData(1)) + return 1; + return 0; /* success */ +} + +int wmt_swi2c_WriteAck(unsigned char byte) +{ + int ret; + int bit; + + for (bit = 7; bit >= 0; bit--) { + wmt_swi2c_SetData(byte & 0x80); + byte <<= 1; + if (wmt_swi2c_SetClock(1)) + return 1; + if (wmt_swi2c_SetClock(0)) + return 1; + } + ret = 0; + wmt_swi2c_SetSDAInput(); + if (wmt_swi2c_SetClock(1)) + ret = 1; + else if (wmt_swi2c_GetSDA()) + ret = (wmt_swi2c_SetClock(0)) ? 1 : 0; + else if (wmt_swi2c_SetClock(0)) + ret = 1; + wmt_swi2c_SetSDAOutput(); + return ret; +} + +int wmt_swi2c_ReadAck(unsigned char *byte, int last) +{ + unsigned char i; + unsigned char Data = 0; + + wmt_swi2c_SetSDAInput(); + + for (i = 0; i < 8; i++) { + if (wmt_swi2c_SetClock(1)) { + wmt_swi2c_SetSDAOutput(); + return 1; + } + Data <<= 1; + wmt_swi2c_delay(0); + Data |= wmt_swi2c_GetSDA(); + if (wmt_swi2c_SetClock(0)) { + wmt_swi2c_SetSDAOutput(); + return 1; + } + } + + *byte = Data; + wmt_swi2c_SetSDAOutput(); + + wmt_swi2c_delay(0); + if (wmt_swi2c_SetData((last) ? 1 : 0)) + return 1; + if (wmt_swi2c_SetClock(1)) + return 1; + wmt_swi2c_delay(0); + if (wmt_swi2c_SetClock(0)) + return 1; + wmt_swi2c_delay(0); + return 0; +} + +int wmt_swi2c_tx( + char addr, + char *buf, + int cnt, + int *ret_cnt +) +{ + int ret = 0; + unsigned char i; + + wmt_swi2c_lock(1); + + ret |= wmt_swi2c_StartI2C(); + if (ret) + goto tx_end; + ret |= wmt_swi2c_WriteAck(addr); + if (ret) + goto tx_end; + for (i = 0; i < cnt; i++) { + ret |= wmt_swi2c_WriteAck(buf[i]); + if (ret) + goto tx_end; + } + ret |= wmt_swi2c_StopI2C(); +tx_end: + wmt_swi2c_lock(0); + return ret; +} + +int wmt_swi2c_rx( + char addr, + char *buf, + int cnt, + int *ret_cnt +) +{ + int ret = 0; + int i; + + wmt_swi2c_lock(1); + + ret |= wmt_swi2c_StartI2C(); + if (ret) + goto rx_end; + ret |= wmt_swi2c_WriteAck(addr | 0x01); + if (ret) + goto rx_end; + for (i = 0; i < cnt; i++) { + ret |= wmt_swi2c_ReadAck((unsigned char *)&buf[i], + (i == (cnt - 1))); + if (ret) + goto rx_end; + } + ret |= wmt_swi2c_StopI2C(); +rx_end: + wmt_swi2c_lock(0); + return ret; +} + +void wmt_swi2c_reg_bk(struct swi2c_reg_s *reg_p, + struct swi2c_reg_bk_t *reg_bk, int bk) +{ + if (bk) { + reg_bk->gpio_en = inw(reg_p->gpio_en); + reg_bk->out_en = inw(reg_p->out_en); + reg_bk->data_out = inw(reg_p->data_out); + reg_bk->pull_en = inw(reg_p->pull_en); + } else { + outw(reg_bk->gpio_en, reg_p->gpio_en); + outw(reg_bk->out_en, reg_p->out_en); + outw(reg_bk->data_out, reg_p->data_out); + outw(reg_bk->pull_en, reg_p->pull_en); + } +} + +int wmt_swi2c_read( + struct swi2c_handle_s *handle, + char addr, + char index, + char *buf, + int cnt +) +{ + int ret = 0; + char buffer[24]; + int temp = 0; + struct swi2c_reg_bk_t scl_bk, sda_bk; + + swi2c_scl = handle->scl_reg; + swi2c_sda = handle->sda_reg; + + wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 1); + wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 1); + + buffer[0] = index; + ret = wmt_swi2c_tx(addr, buffer, 1, &temp); + if (ret) { + DPRINT("[SWI2C] *E* tx fail\n"); + goto exit; + } + ret = wmt_swi2c_rx(addr, buf, cnt, &temp); + if (ret) { + DPRINT("[SWI2C] *E* rx fail\n"); + goto exit; + } +exit: + wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 0); + wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 0); + return ret; +} +EXPORT_SYMBOL(wmt_swi2c_read); + +int wmt_swi2c_write( + struct swi2c_handle_s *handle, + char addr, + char index, + char *buf, + int cnt +) +{ + int ret = 0; + char buffer[24]; + int temp; + struct swi2c_reg_bk_t scl_bk, sda_bk; + + swi2c_scl = handle->scl_reg; + swi2c_sda = handle->sda_reg; + + wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 1); + wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 1); + + buffer[0] = index; + buffer[1] = *buf; + ret = wmt_swi2c_tx(addr, buffer, cnt, &temp); + if (ret) { + DPRINT("[SWI2C] *E* tx fail\n"); + goto exit; + } +exit: + wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 0); + wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 0); + return ret; +} +EXPORT_SYMBOL(wmt_swi2c_write); + +int wmt_swi2c_check(struct swi2c_handle_s *handle) +{ + int ret = 0; +#if 0 + struct swi2c_reg_s *reg_p; + struct swi2c_reg_bk_t scl_bk, sda_bk; + + swi2c_scl = handle->scl_reg; + swi2c_sda = handle->sda_reg; + + wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 1); + wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 1); + reg_p = handle->scl_reg; + do { + outw(inw(reg_p->gpio_en) | reg_p->bit_mask, reg_p->gpio_en); + outw(inw(reg_p->out_en) | reg_p->bit_mask, reg_p->out_en); + outw(inw(reg_p->data_out) & ~reg_p->bit_mask, reg_p->data_out); + + outw(inw(reg_p->out_en) & ~reg_p->bit_mask, reg_p->out_en); + if (reg_p->pull_en) + outw(inw(reg_p->pull_en) & ~reg_p->pull_en_bit_mask, + reg_p->pull_en); + if (inw(reg_p->data_in) & reg_p->bit_mask) { + if (reg_p == handle->sda_reg) + break; + reg_p = handle->sda_reg; + } else { + ret = 1; + break; + } + } while (1); + wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 0); + wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 0); + DPRINT("[SWI2C] %s exist\n", (ret) ? "not" : ""); +#endif + return ret; +} +EXPORT_SYMBOL(wmt_swi2c_check); diff --git a/common/wmt_display/sw_i2c.h b/common/wmt_display/sw_i2c.h new file mode 100755 index 0000000..593fd08 --- /dev/null +++ b/common/wmt_display/sw_i2c.h @@ -0,0 +1,63 @@ +/*++ + * linux/drivers/video/wmt/sw_i2c.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef _SWI2C_H_ +#define _SWI2C_H_ + +struct swi2c_reg_s { + unsigned int bit_mask; + unsigned int gpio_en; + unsigned int out_en; + unsigned int data_in; + unsigned int data_out; + unsigned int pull_en_bit_mask; + unsigned int pull_en; +}; +#define swi2c_reg_t struct swi2c_reg_s + +struct swi2c_handle_s { + struct swi2c_reg_s *scl_reg; + struct swi2c_reg_s *sda_reg; +}; +#define swi2c_handle_t struct swi2c_handle_s + +int wmt_swi2c_read( + struct swi2c_handle_s *handle, + char addr, + char index, + char *buf, + int cnt +); + +int wmt_swi2c_write( + struct swi2c_handle_s *handle, + char addr, + char index, + char *buf, + int cnt +); + +int wmt_swi2c_check(struct swi2c_handle_s *handle); + +#endif + diff --git a/common/wmt_display/uboot-vpp.c b/common/wmt_display/uboot-vpp.c new file mode 100755 index 0000000..7343cae --- /dev/null +++ b/common/wmt_display/uboot-vpp.c @@ -0,0 +1,298 @@ +/*++ + * common/wmt_display/uboot-vpp.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> + +#define DEBUG + +#include "vpp.h" +#include "vout.h" +#include "minivgui.h" + +#define WMT_DISPLAY + +#include "../../board/wmt/include/wmt_clk.h" + +#include "hw_devices.h" +#include "wmt_display.h" +#include "vout.h" + +struct wmt_display_param_t g_display_param; +struct wmt_display_param_t g_display_param2; +struct wmt_pwm_setting_t g_pwm_setting; +struct gpio_operation_t g_lcd_pw_pin; + +#ifdef CONFIG_VPP_SHENZHEN +struct wmt_backlight_param_t g_backlight_param; +#endif + +int g_display_vaild; +unsigned int g_fb_phy; +unsigned int g_img_phy; +int g_logo_x; +int g_logo_y; +logo_scale_t g_logo_scale = LOGO_NOT_SCALE; + +char *video_str[] = { + "SDA", "SDD" , "LCD", "DVI" , "HDMI", "DVO2HDMI", "LVDS", "VGA" +}; + +extern int vo_dvi_initial(void); +extern int vo_hdmi_initial(void); +extern int vo_lvds_initial(void); +extern int vo_virtual_initial(void); +extern int vt1632_module_init(void); +extern int sil902x_module_init(void); +extern void vpp_init(void); +extern struct vout_dev_t *lcd_get_dev(void); +extern void vpp_config(struct vout_info_t *info); + +static unsigned int alignmentMemory(unsigned int memtotal) +{ + unsigned int memmax = 2; + + while (memtotal > memmax) { + memmax *= 2; + } + return memmax; +} + +static unsigned int wmt_get_fb(unsigned int memtotal, unsigned int mbsize) +{ + unsigned int addr; + + addr = alignmentMemory(memtotal); + addr <<= 20; + addr -= 1920 * 1200 * 4; /* avoid kernel change resolution */ + addr -= 1280; /* avoid govr prefetch 1280 byte over memory boundary */ + return addr; +} + +static int wmt_init_check(void) +{ + char *tmp; + + check_tf_boot(); + check_display_direction(); //added by howayhuo + + g_fb_phy = 0; + if ((tmp = getenv (ENV_DIRECTFB)) != NULL) + g_fb_phy = (unsigned int)simple_strtoul(tmp, NULL, 16); + + if (g_fb_phy == 0) { + unsigned int memtotal; + unsigned int mbsize; + + /* we must check "memtotal" because we get framebuf from it */ + if ((tmp = getenv (ENV_MEMTOTAL)) != NULL) { + memtotal = (unsigned int)simple_strtoul(tmp, NULL, 10); + } else { + printf("err:need %s to cal fb addr\n", ENV_MEMTOTAL); + return -1; + } + + if ((tmp = getenv ("mbsize")) != NULL) { + mbsize = (unsigned int)simple_strtoul (tmp, NULL, 10); + } else { + printf("err:need %s to cal fb addr\n", "mbsize"); + return -1; + } + g_fb_phy = wmt_get_fb(memtotal, mbsize); + } + + if ((tmp = getenv (ENV_IMGADDR)) != NULL) + g_img_phy = (unsigned int)simple_strtoul (tmp, NULL, 16); + else { + printf("%s is not found,(display show) invaild\n", ENV_IMGADDR); + g_img_phy = 0xFFFF; + } + return 0; +} + +#if 0 +int uboot_vpp_alloc_framebuffer(unsigned int resx, unsigned int resy) +{ + return 0; +} +#endif + +void vpp_mod_init(void) +{ +#ifdef WMT_FTBLK_GOVRH + govrh_mod_init(); +#endif +#ifdef WMT_FTBLK_SCL + scl_mod_init(); +#endif + /* register vout interface */ + vo_dvi_initial(); + vo_hdmi_initial(); + vo_lvds_initial(); +} + +void vpp_device_init(void) +{ + auto_pll_divisor(DEV_PWM,CLK_ENABLE, 0, 0); + lcd_module_init(); + lcd_oem_init(); + lcd_lw700at9003_init(); + lcd_at070tn83_init(); + lcd_a080sn01_init(); + lcd_ek08009_init(); + lcd_HSD101PFW2_init(); + lcd_LVDS_1024x600_init(); + + vt1632_module_init(); + vt1625_module_init(); + sil902x_module_init(); +} + +int wmt_graphic_init(void) +{ + struct vout_info_t *info; + int i; + int y_bpp, c_bpp; + struct vout_t *vo; + + if (wmt_init_check()) + return -1; + + vpp_mod_init(); + vpp_device_init(); + vpp_init(); + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + struct fb_videomode vmode; + vdo_framebuf_t *fb; + unsigned int pixel_size, line_size; + mv_surface s; + + info = vout_info[i]; + if (!info) + break; + + memset(&vmode, 0, sizeof(struct fb_videomode)); + vmode.xres = info->resx; + vmode.yres = info->resy; + vmode.refresh = info->fps; + vmode.vmode = (info->option & VPP_OPT_INTERLACE) ? + FB_VMODE_INTERLACED : 0; + vout_find_match_mode(i, &vmode, 1); +#if 0 + printf("fb %d\n", i); + vpp_show_videomode("uboot", &vmode); +#endif + info->resx = vmode.xres; + info->resy = vmode.yres; + + /* get framebuffer parameter */ + fb = &info->fb; + fb->col_fmt = g_vpp.mb_colfmt; + fb->img_w = info->resx; + fb->img_h = info->resy; + fb->fb_w = vpp_calc_fb_width(fb->col_fmt, info->resx); + fb->fb_h = info->resy; + + info->resx_virtual = fb->fb_w; + info->resy_virtual = fb->fb_h; + vpp_get_colfmt_bpp(fb->col_fmt, &y_bpp, &c_bpp); + pixel_size = y_bpp / 8; + line_size = fb->fb_w * pixel_size; + g_fb_phy -= (fb->fb_h * line_size); + fb->y_addr = g_fb_phy; + fb->c_addr = 0; + /* init surface */ + s.width = fb->img_w; + s.height = fb->img_h; + s.startAddr = (char *) fb->y_addr; + s.bits_per_pixel = pixel_size * 8; + s.lineBytes = line_size; + mv_initSurface(i,&s); + + /* clear frame buffer */ + memset((void *)fb->y_addr, 0, fb->fb_h * line_size); + vout_config(info, &vmode, &info->fb); +#if 0 + DBG_MSG("[UBOOT] fb%d(%dx%d)\n", i, vmode.xres, vmode.yres); + vpp_show_framebuf("uboot", fb); +#endif + } + + /* enable vout */ + for (i = 0; i < VPP_VOUT_NUM; i++) { + int blank; + + vo = vout_get_entry(i); + if (!vo) + continue; + blank = (vo->status & VPP_VOUT_STS_ACTIVE) ? + VOUT_BLANK_UNBLANK : VOUT_BLANK_POWERDOWN; + blank = (vo->status & VPP_VOUT_STS_BLANK) ? + VOUT_BLANK_NORMAL : blank; + vout_set_blank(i, blank); + } + + /* set pwm for LCD backlight */ + g_display_param.vout = VPP_VOUT_DVI; + if ( lcd_get_dev() || (lcd_get_lvds_id() != LCD_PANEL_MAX)) + g_display_param.vout = VPP_VOUT_LCD; + + if (g_display_param.vout == VPP_VOUT_LCD) { + parse_pwm_params(ENV_DISPLAY_PWM, NULL); + parse_gpio_operation(ENV_LCD_POWER); + if ((g_display_vaild&PWMDEFMASK) == PWMDEFTP) + lcd_blt_set_pwm(g_pwm_setting.pwm_no, + g_pwm_setting.duty, g_pwm_setting.period); + else { + /* fan : may need to check PWM power .. */ + pwm_set_period(g_pwm_setting.pwm_no, + g_pwm_setting.period - 1); + pwm_set_duty(g_pwm_setting.pwm_no, + g_pwm_setting.duty - 1); + pwm_set_control(g_pwm_setting.pwm_no, + (g_pwm_setting.duty - 1) ? 0x34 : 0x8); + pwm_set_gpio(g_pwm_setting.pwm_no, + g_pwm_setting.duty - 1); + pwm_set_scalar(g_pwm_setting.pwm_no, + g_pwm_setting.scalar - 1); + } + lcd_set_enable(1); + } +#if 0 + p_govrh->dump_reg(); + p_govrh2->dump_reg(); +// hdmi_reg_dump(); +// lvds_reg_dump(); +#endif + g_display_vaild |= DISPLAY_ENABLE; + return 0; +} +#undef WMT_DISPLAY + diff --git a/common/wmt_display/vout-wmt.c b/common/wmt_display/vout-wmt.c new file mode 100755 index 0000000..2e2c71f --- /dev/null +++ b/common/wmt_display/vout-wmt.c @@ -0,0 +1,1344 @@ +/*++ + * linux/drivers/video/wmt/vout-wmt.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ + +#include "vpp.h" + +#ifndef CFG_LOADER +static int vo_plug_flag; +#endif +int vo_plug_vout; +int (*vo_plug_func)(int hotplug); +enum vout_mode_t dvo_vout_mode; +enum vout_mode_t int_vout_mode; +int hdmi_cur_plugin; +struct vout_t *vo_poll_vout; + +/* GPIO 10 & 11 */ +struct swi2c_reg_s vo_gpio_scl = { + .bit_mask = BIT10, + .gpio_en = (__GPIO_BASE + 0x40), + .out_en = (__GPIO_BASE + 0x80), + .data_in = (__GPIO_BASE + 0x00), + .data_out = (__GPIO_BASE + 0xC0), + .pull_en = (__GPIO_BASE + 0x480), + .pull_en_bit_mask = BIT10, +}; + +struct swi2c_reg_s vo_gpio_sda = { + .bit_mask = BIT11, + .gpio_en = (__GPIO_BASE + 0x40), + .out_en = (__GPIO_BASE + 0x80), + .data_in = (__GPIO_BASE + 0x00), + .data_out = (__GPIO_BASE + 0xC0), + .pull_en = (__GPIO_BASE + 0x480), + .pull_en_bit_mask = BIT11, +}; + +struct swi2c_handle_s vo_swi2c_dvi = { + .scl_reg = &vo_gpio_scl, + .sda_reg = &vo_gpio_sda, +}; + +#define DVI_POLL_TIME_MS 1000 + +extern void hdmi_config_audio(struct vout_audio_t *info); + +/*---------------------------------- API ------------------------------------*/ +#ifdef DEBUG +void vout_print_entry(struct vout_t *vo) +{ + if (vo == 0) + return; + + MSG(" =============== vout %d ===============\n", vo->num); + MSG("fix 0x%x", vo->fix_cap); + MSG("(inf %d,bus %d,govr %d,ext dev %d,fix plug %d,aud %d,edid %d)\n", + (vo->fix_cap & VOUT_CAP_INTERFACE), + (vo->fix_cap & VOUT_CAP_BUS) >> 8, + (vo->fix_cap & VOUT_CAP_GOVR) >> 12, + (vo->fix_cap & VOUT_CAP_EXT_DEV) ? 1 : 0, + (vo->fix_cap & VOUT_CAP_FIX_PLUG) ? 1 : 0, + (vo->fix_cap & VOUT_CAP_AUDIO) ? 1 : 0, + (vo->fix_cap & VOUT_CAP_EDID) ? 1 : 0); + MSG("info %d,%s\n", vo->info->num, vpp_mod_str[vo->govr->mod]); + MSG("inf 0x%x,dev 0x%x\n", (int)vo->inf, (int)vo->dev); + MSG("resx %d,resy %d,fps %d\n", vo->resx, vo->resy, vo->fps); + MSG("pixclk %d,option %d,%d,%d,disable %d\n", vo->pixclk, + vo->option[0], vo->option[1], vo->option[2], vo->disable); + MSG("sts(reg %d,act %d,plug %d,edid %d,blank %d,pwrdn %d,cp %d)\n", + (vo->status & VPP_VOUT_STS_REGISTER) ? 1 : 0, + (vo->status & VPP_VOUT_STS_ACTIVE) ? 1 : 0, + (vo->status & VPP_VOUT_STS_PLUGIN) ? 1 : 0, + (vo->status & VPP_VOUT_STS_EDID) ? 1 : 0, + (vo->status & VPP_VOUT_STS_BLANK) ? 1 : 0, + (vo->status & VPP_VOUT_STS_POWERDN) ? 1 : 0, + (vo->status & VPP_VOUT_STS_CONTENT_PROTECT) ? 1 : 0); + + if (vo->inf) { + MSG(" ===== inf entry =====\n"); + MSG("mode %d, %s\n", + vo->inf->mode, vout_inf_str[vo->inf->mode]); + } + + if (vo->dev) { + MSG(" ===== dev entry =====\n"); + MSG("name %s,inf %d,%s\n", vo->dev->name, + vo->dev->mode, vout_inf_str[vo->dev->mode]); + MSG("vout 0x%x,capability 0x%x\n", + (int)vo->dev->vout, vo->dev->capability); + } +} +#endif + +int vo_i2c_proc(int id, unsigned int addr, unsigned int index, + char *pdata, int len) +{ + struct swi2c_handle_s *handle = 0; + int ret = 0; + + switch (id) { + case 1: /* dvi */ + if (lcd_get_type()) /* share pin with LVDS */ + return -1; + handle = &vo_swi2c_dvi; + break; + default: + break; + } + + if (handle) { + if (wmt_swi2c_check(handle)) + return -1; + if (addr & 0x1) { /* read */ + *pdata = 0xff; +#ifdef CONFIG_WMT_EDID + ret = wmt_swi2c_read(handle, addr & ~0x1, + index, pdata, len); +#else + ret = -1; +#endif + } else { /* write */ + DBG_ERR("not support sw i2c write\n"); + } + } + return ret; +} + +#ifndef CONFIG_UBOOT +static void vo_do_plug(struct work_struct *ptr) +{ + struct vout_t *vo; + int plugin; + + if (vo_plug_func == 0) + return; + + vo = vout_get_entry(vo_plug_vout); + govrh_set_dvo_enable(vo->govr, 1); + plugin = vo_plug_func(1); +/* govrh_set_dvo_enable(vo->govr, plugin); */ + vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin); + vo_plug_flag = 0; + DBG_DETAIL("vo_do_plug %d\n", plugin); + /* GPIO irq enable */ + vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO, 0x80, 7, 1); + /* GPIO input mode */ + vppif_reg32_write(GPIO_BASE_ADDR + 0x80, 0x1 << VPP_VOINT_NO, + VPP_VOINT_NO, 0x0); +#ifdef __KERNEL__ + vpp_netlink_notify_plug(VPP_VOUT_NUM_DVI, plugin); +#endif + return; +} + +DECLARE_DELAYED_WORK(vo_plug_work, vo_do_plug); + +static irqreturn_t vo_plug_interrupt_routine +( + int irq, /*!<; // irq id */ + void *dev_id /*!<; // device id */ +) +{ + DBG_DETAIL("Enter\n"); + if ((inb(GPIO_BASE_ADDR + 0x360) & + (0x1 << VPP_VOINT_NO)) == 0) + return IRQ_NONE; + + /* clear int status */ + outb(0x1 << VPP_VOINT_NO, GPIO_BASE_ADDR + 0x360); +#ifdef __KERNEL__ + /* if (vo_plug_flag == 0) { */ + /* GPIO irq disable */ + vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO, 0x80, 7, 0); + schedule_delayed_work(&vo_plug_work, HZ/5); + vo_plug_flag = 1; + /* } */ +#else + if (vo_plug_func) + vo_do_plug(0); +#endif + return IRQ_HANDLED; +} + +#define CONFIG_VO_POLL_WORKQUEUE +struct timer_list vo_poll_timer; +#ifdef CONFIG_VO_POLL_WORKQUEUE +static void vo_do_poll(struct work_struct *ptr) +{ + struct vout_t *vo; + + vo = vo_poll_vout; + if (vo) { + if (vo->dev) + vo->dev->poll(); + mod_timer(&vo_poll_timer, + jiffies + msecs_to_jiffies(vo_poll_timer.data)); + } + return; +} + +DECLARE_DELAYED_WORK(vo_poll_work, vo_do_poll); +#else +struct tasklet_struct vo_poll_tasklet; +static void vo_do_poll_tasklet +( + unsigned long data /*!<; // tasklet input data */ +) +{ + struct vout_t *vo; + + vpp_lock(); + vo = vo_poll_vout; + if (vo) { + if (vo->dev) + vo->dev->poll(); + mod_timer(&vo_poll_timer, + jiffies + msecs_to_jiffies(vo_poll_timer.data)); + } + vpp_unlock(); +} +#endif + +void vo_do_poll_tmr(int ms) +{ +#ifdef CONFIG_VO_POLL_WORKQUEUE + schedule_delayed_work(&vo_poll_work, msecs_to_jiffies(ms)); +#else + tasklet_schedule(&vo_poll_tasklet); +#endif +} + +static void vo_set_poll(struct vout_t *vo, int on, int ms) +{ + DMSG("%d\n", on); + + if (on) { + vo_poll_vout = vo; + if (vo_poll_timer.function) { + vo_poll_timer.data = ms / 2; + mod_timer(&vo_poll_timer, + jiffies + msecs_to_jiffies(vo_poll_timer.data)); + } else { + init_timer(&vo_poll_timer); + vo_poll_timer.data = ms / 2; + vo_poll_timer.function = (void *) vo_do_poll_tmr; + vo_poll_timer.expires = jiffies + + msecs_to_jiffies(vo_poll_timer.data); + add_timer(&vo_poll_timer); + } +#ifndef CONFIG_VO_POLL_WORKQUEUE + tasklet_init(&vo_poll_tasklet, vo_do_poll_tasklet, 0); +#endif + } else { + del_timer(&vo_poll_timer); +#ifndef CONFIG_VO_POLL_WORKQUEUE + tasklet_kill(&vo_poll_tasklet); +#endif + vo_poll_vout = 0; + } +} +#endif + +void vout_set_int_type(int type) +{ + unsigned char reg; + + reg = inb(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO); + reg &= ~0x7; + switch (type) { + case 0: /* low level */ + case 1: /* high level */ + case 2: /* falling edge */ + case 3: /* rising edge */ + case 4: /* rising edge or falling */ + reg |= type; + break; + default: + break; + } + outb(reg, GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO); +} +EXPORT_SYMBOL(vout_set_int_type); + +void vout_set_int_enable(int enable) +{ + vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + + VPP_VOINT_NO, 0x80, 7, enable); /* GPIO irq enable/disable */ +} +EXPORT_SYMBOL(vout_set_int_enable); + +int vout_get_clr_int(void) +{ + if ((inb(GPIO_BASE_ADDR + 0x360) & + (0x1 << VPP_VOINT_NO)) == 0) + return 1; + /* clear int status */ + outb(0x1 << VPP_VOINT_NO, GPIO_BASE_ADDR + 0x360); + return 0; +} +EXPORT_SYMBOL(vout_get_clr_int); + +static void vo_plug_enable(int enable, void *func, int no) +{ + struct vout_t *vo; + + DBG_DETAIL("%d\n", enable); + vo_plug_vout = no; + vo = vout_get_entry(no); +#ifdef CONFIG_WMT_EXT_DEV_PLUG_DISABLE + vo_plug_func = 0; + govrh_set_dvo_enable(vo->govr, enable); +#else + vo_plug_func = func; + if (vo_plug_func == 0) + return; + + if (enable) { + vppif_reg32_write(GPIO_BASE_ADDR + 0x40, 0x1 << VPP_VOINT_NO, + VPP_VOINT_NO, 0x0); /* GPIO disable */ + vppif_reg32_write(GPIO_BASE_ADDR + 0x80, 0x1 << VPP_VOINT_NO, + VPP_VOINT_NO, 0x0); /* GPIO input mode */ + vppif_reg32_write(GPIO_BASE_ADDR + 0x480, 0x1 << VPP_VOINT_NO, + VPP_VOINT_NO, 0x1); /* GPIO pull enable */ + vppif_reg32_write(GPIO_BASE_ADDR + 0x4c0, 0x1 << VPP_VOINT_NO, + VPP_VOINT_NO, 0x1); /* GPIO pull-up */ +#ifndef CONFIG_UBOOT + vo_do_plug(0); + if (vpp_request_irq(IRQ_GPIO, vo_plug_interrupt_routine, + IRQF_SHARED, "vo plug", (void *) &vo_plug_vout)) + DBG_ERR("request GPIO ISR fail\n"); + + vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO, + 0x80, 7, 1); /* GPIO irq enable */ + } else { + vpp_free_irq(IRQ_GPIO, (void *) &vo_plug_vout); +#endif + } +#endif +} + +/*--------------------------------- DVI ------------------------------------*/ +#ifdef WMT_FTBLK_VOUT_DVI +static int vo_dvi_blank(struct vout_t *vo, enum vout_blank_t arg) +{ + DMSG("(%d, %d)\n", vo->pre_blank, arg); + if(vo->pre_blank == arg) + return 0; + + if (vo->pre_blank == VOUT_BLANK_POWERDOWN) { + if (vo->dev) { +#ifdef __KERNEL__ + if (!g_vpp.dvi_int_disable && vo->dev->interrupt) + vo_plug_enable(VPP_FLAG_ENABLE, + vo->dev->interrupt, vo->num); + else if (vo->dev->poll) + vo_set_poll(vo, (vo->dev->poll) ? 1 : 0, + DVI_POLL_TIME_MS); +#endif + } + } +#ifdef __KERNEL__ + if (arg == VOUT_BLANK_POWERDOWN) + vo_set_poll(vo, 0, 0); +#endif + if (!lcd_get_dev()) /* enable DVO not contain LCD */ + govrh_set_dvo_enable(vo->govr, + (arg == VOUT_BLANK_UNBLANK) ? 1 : 0); + vo->pre_blank = arg; + return 0; +} + +static int vo_dvi_config(struct vout_t *vo, int arg) +{ + struct vout_info_t *vo_info; + + DBG_DETAIL("Enter\n"); + + vo_info = (struct vout_info_t *) arg; + govrh_set_dvo_sync_polar(vo->govr, + (vo_info->option & VPP_DVO_SYNC_POLAR_HI) ? 0 : 1, + (vo_info->option & VPP_DVO_VSYNC_POLAR_HI) ? 0 : 1); + return 0; +} + +static int vo_dvi_init(struct vout_t *vo, int arg) +{ + unsigned int clk_delay; + + DBG_DETAIL("(%d)\n", arg); + + vo->pre_blank = VOUT_BLANK_POWERDOWN; + + lvds_set_enable(0); + govrh_set_dvo_color_format(vo->govr, vo->option[0]); + govrh_set_dvo_outdatw(vo->govr, vo->option[1] & WMT_DISP_FB_DVI_24BIT); + govrh_IGS_set_mode(vo->govr, 0, WMT_DISP_FB_GET_RGB_MODE(vo->option[1]), + (vo->option[1] & WMT_DISP_FB_MSB) ? 1 : 0); + govrh_IGS_set_RGB_swap(vo->govr, WMT_DISP_FB_RGB_SWAP(vo->option[1])); + clk_delay = (vo->option[1] & WMT_DISP_FB_DVI_24BIT) ? + VPP_GOVR_DVO_DELAY_24 : VPP_GOVR_DVO_DELAY_12; + govrh_set_dvo_clock_delay(vo->govr, ((clk_delay & BIT14) != 0x0), + clk_delay & 0x3FFF); + if (vo->dev) { + vo->dev->set_mode(&vo->option[0]); + vo->dev->set_power_down(VPP_FLAG_DISABLE); + if (!g_vpp.dvi_int_disable && vo->dev->interrupt) + vo_plug_enable(VPP_FLAG_ENABLE, + vo->dev->interrupt, vo->num); +#ifdef __KERNEL__ + else if (vo->dev->poll) { + vo_set_poll(vo, (vo->dev->poll) ? 1 : 0, + DVI_POLL_TIME_MS); + } +#endif + vout_change_status(vo, VPP_VOUT_STS_PLUGIN, + vo->dev->check_plugin(0)); + } + vo->govr->fb_p->set_csc(vo->govr->fb_p->csc_mode); + if (!lcd_get_dev()) { + govrh_set_dvo_enable(vo->govr, + (vo->status & VPP_VOUT_STS_BLANK) ? 0 : 1); + } + return 0; +} + +static int vo_dvi_uninit(struct vout_t *vo, int arg) +{ + DBG_DETAIL("(%d)\n", arg); + + vo_plug_enable(VPP_FLAG_DISABLE, 0, VPP_VOUT_NUM); + govrh_set_dvo_enable(vo->govr, VPP_FLAG_DISABLE); +#ifdef __KERNEL__ + vo_set_poll(vo, 0, DVI_POLL_TIME_MS); +#endif + return 0; +} + +static int vo_dvi_chkplug(struct vout_t *vo, int arg) +{ + int plugin = 1; + + DBG_MSG("plugin %d\n", plugin); + return plugin; +} + +static int vo_dvi_get_edid(struct vout_t *vo, int arg) +{ + char *buf; + int i, cnt; + + DBG_DETAIL("Enter\n"); + + buf = (char *) arg; + memset(&buf[0], 0x0, 128 * EDID_BLOCK_MAX); + if (vpp_i2c_read(VPP_DVI_EDID_ID, 0xA0, 0, &buf[0], 128)) { + DBG_ERR("read edid\n"); + return 1; + } + + if (edid_checksum(buf, 128)) { + DBG_ERR("checksum\n"); + return 1; + } + + cnt = buf[0x7E]; + if (cnt >= 3) + cnt = 3; + for (i = 1; i <= cnt; i++) { + vpp_i2c_read(VPP_DVI_EDID_ID, 0xA0, 0x80 * i, + &buf[128 * i], 128); + } + return 0; +} + +struct vout_inf_t vo_dvi_inf = { + .mode = VOUT_INF_DVI, + .init = vo_dvi_init, + .uninit = vo_dvi_uninit, + .blank = vo_dvi_blank, + .config = vo_dvi_config, + .chkplug = vo_dvi_chkplug, + .get_edid = vo_dvi_get_edid, +}; + +int vo_dvi_initial(void) +{ + vout_inf_register(VOUT_INF_DVI, &vo_dvi_inf); + return 0; +} +module_init(vo_dvi_initial); + +#endif /* WMT_FTBLK_VOUT_DVI */ + +/*---------------------------------- HDMI -----------------------------------*/ +void vo_hdmi_set_clock(int enable) +{ + DBG_DETAIL("(%d)\n", enable); + + enable = (enable) ? CLK_ENABLE : CLK_DISABLE; + vpp_set_clock_enable(DEV_HDMII2C, enable, 0); + vpp_set_clock_enable(DEV_HDMI, enable, 0); + vpp_set_clock_enable(DEV_HDCE, enable, 0); +} + +#ifdef WMT_FTBLK_VOUT_HDMI +#ifdef __KERNEL__ +struct timer_list hdmi_cp_timer; +static struct timer_list hdmi_plug_timer; +#endif + +void vo_hdmi_cp_set_enable_tmr(int sec) +{ +#ifdef __KERNEL__ + int ms = sec * 1000; +#endif + + DBG_MSG("[HDMI] set enable tmr %d sec\n", sec); + + if (sec == 0) { + hdmi_set_cp_enable(VPP_FLAG_ENABLE); + return ; + } +#ifdef __KERNEL__ + if (hdmi_cp_timer.function) + del_timer(&hdmi_cp_timer); + init_timer(&hdmi_cp_timer); + hdmi_cp_timer.data = VPP_FLAG_ENABLE; + hdmi_cp_timer.function = (void *) hdmi_set_cp_enable; + hdmi_cp_timer.expires = jiffies + msecs_to_jiffies(ms); + add_timer(&hdmi_cp_timer); +#else + hdmi_set_cp_enable(VPP_FLAG_ENABLE); +#endif +} +EXPORT_SYMBOL(vo_hdmi_cp_set_enable_tmr); + +static int vo_hdmi_blank(struct vout_t *vo, enum vout_blank_t arg) +{ + int enable; + + DBG_DETAIL("(%d)\n", arg); + + enable = (arg == VOUT_BLANK_UNBLANK) ? 1 : 0; + if (g_vpp.hdmi_cp_enable && enable) + vo_hdmi_cp_set_enable_tmr(2); + else + hdmi_set_cp_enable(VPP_FLAG_DISABLE); + hdmi_set_enable(enable); + hdmi_set_power_down((enable) ? 0 : 1); + return 0; +} + +#ifndef CFG_LOADER +static irqreturn_t vo_hdmi_cp_interrupt +( + int irq, /*!<; // irq id */ + void *dev_id /*!<; // device id */ +) +{ + struct vout_t *vo; + + DBG_DETAIL("%d\n", irq); + vo = vout_get_entry(VPP_VOUT_NUM_HDMI); + switch (hdmi_check_cp_int()) { + case 1: + if (hdmi_cp) + hdmi_cp->enable(VPP_FLAG_DISABLE); + vo_hdmi_cp_set_enable_tmr(HDMI_CP_TIME); + vout_change_status(vo, VPP_VOUT_STS_CONTENT_PROTECT, 0); + vpp_netlink_notify_cp(0); + break; + case 0: + vout_change_status(vo, VPP_VOUT_STS_CONTENT_PROTECT, 1); + vpp_netlink_notify_cp(1); + break; + case 2: + hdmi_ri_tm_cnt = 3 * 30; + break; + default: + break; + } + return IRQ_HANDLED; +} + +#ifdef __KERNEL__ +static void vo_hdmi_do_plug(struct work_struct *ptr) +#else +static void vo_hdmi_do_plug(void) +#endif +{ + struct vout_t *vo; + int plugin; + int option = 0; + + plugin = hdmi_check_plugin(1); + vo = vout_get_entry(VPP_VOUT_NUM_HDMI); + vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin); + if (plugin) { + option = vout_get_edid_option(VPP_VOUT_NUM_HDMI); +#ifdef CONFIG_VPP_DEMO + option |= (EDID_OPT_HDMI + EDID_OPT_AUDIO); +#endif + hdmi_set_option(option); + } else { + g_vpp.hdmi_bksv[0] = g_vpp.hdmi_bksv[1] = 0; + } + vo_hdmi_blank(vo, (vo->status & VPP_VOUT_STS_BLANK) ? 1 : !(plugin)); + if (!g_vpp.hdmi_certify_flag) + hdmi_hotplug_notify(plugin); + DBG_MSG("%d\n", plugin); + return; +} +DECLARE_WORK(vo_hdmi_plug_work, vo_hdmi_do_plug); + +static void hdmi_handle_plug(vpp_flag_t enable) +{ + schedule_work(&vo_hdmi_plug_work); +} + +static void vo_hdmi_handle_plug_tmr(int ms) +{ + static int timer_init; + + if (timer_init == 0) { + init_timer(&hdmi_plug_timer); + hdmi_plug_timer.data = VPP_FLAG_ENABLE; + hdmi_plug_timer.function = (void *) hdmi_handle_plug; + timer_init = 1; + } + hdmi_plug_timer.expires = jiffies + msecs_to_jiffies(ms); + mod_timer(&hdmi_plug_timer, hdmi_plug_timer.expires); +} + +static irqreturn_t vo_hdmi_plug_interrupt +( + int irq, /*!<; // irq id */ + void *dev_id /*!<; // device id */ +) +{ + DBG_MSG("vo_hdmi_plug_interrupt %d\n", irq); + hdmi_clear_plug_status(); + if (g_vpp.hdmi_certify_flag) + vo_hdmi_do_plug(0); + else + vo_hdmi_handle_plug_tmr(HDMI_PLUG_DELAY); + return IRQ_HANDLED; +} +#endif + +static int vo_hdmi_init(struct vout_t *vo, int arg) +{ + DBG_DETAIL("(%d)\n", arg); + + vo_hdmi_set_clock(1); + vout_change_status(vout_get_entry(VPP_VOUT_NUM_HDMI), + VPP_VOUT_STS_PLUGIN, hdmi_check_plugin(0)); + hdmi_enable_plugin(1); + + if (g_vpp.hdmi_disable) + return 0; +#ifndef CONFIG_UBOOT + if (vpp_request_irq(VPP_IRQ_HDMI_CP, vo_hdmi_cp_interrupt, + SA_INTERRUPT, "hdmi cp", (void *) 0)) { + DBG_ERR("*E* request HDMI ISR fail\n"); + } + if (vpp_request_irq(VPP_IRQ_HDMI_HPDH, vo_hdmi_plug_interrupt, + SA_INTERRUPT, "hdmi plug", (void *) 0)) { + DBG_ERR("*E* request HDMI ISR fail\n"); + } + if (vpp_request_irq(VPP_IRQ_HDMI_HPDL, vo_hdmi_plug_interrupt, + SA_INTERRUPT, "hdmi plug", (void *) 0)) { + DBG_ERR("*E* request HDMI ISR fail\n"); + } +#endif + hdmi_set_enable((vo->status & VPP_VOUT_STS_BLANK) ? + VPP_FLAG_DISABLE : VPP_FLAG_ENABLE); + return 0; +} + +static int vo_hdmi_uninit(struct vout_t *vo, int arg) +{ + DBG_DETAIL("(%d)\n", arg); + hdmi_enable_plugin(0); + hdmi_set_cp_enable(VPP_FLAG_DISABLE); + hdmi_set_enable(VPP_FLAG_DISABLE); +#ifndef CONFIG_UBOOT + vpp_free_irq(VPP_IRQ_HDMI_CP, (void *) 0); + vpp_free_irq(VPP_IRQ_HDMI_HPDH, (void *) 0); + vpp_free_irq(VPP_IRQ_HDMI_HPDL, (void *) 0); +#endif + vo_hdmi_set_clock(0); + return 0; +} + +static int vo_hdmi_config(struct vout_t *vo, int arg) +{ + struct vout_info_t *vo_info; + vdo_color_fmt colfmt; + + hdmi_set_enable(0); + vo_info = (struct vout_info_t *) arg; + + DBG_DETAIL("(%dx%d@%d)\n", vo_info->resx, vo_info->resy, vo_info->fps); + + /* 1280x720@60, HDMI pixel clock 74250060 not 74500000 */ + if ((vo_info->resx == 1280) + && (vo_info->resy == 720) && (vo_info->pixclk == 74500000)) + vo_info->pixclk = 74250060; + colfmt = (vo->option[0] == VDO_COL_FMT_YUV422V) ? + VDO_COL_FMT_YUV422H : vo->option[0]; + hdmi_cur_plugin = hdmi_check_plugin(0); + hdmi_info.option = (hdmi_cur_plugin) ? + vout_get_edid_option(VPP_VOUT_NUM_HDMI) : 0; + hdmi_info.outfmt = colfmt; + hdmi_info.vic = hdmi_get_vic(vo_info->resx, vo_info->resy, + vo_info->fps, (vo_info->option & VPP_OPT_INTERLACE) ? 1 : 0); + + govrh_set_csc_mode(vo->govr, vo->govr->fb_p->csc_mode); + hdmi_set_sync_low_active((vo_info->option & VPP_DVO_SYNC_POLAR_HI) ? + 0 : 1, (vo_info->option & VPP_DVO_VSYNC_POLAR_HI) ? 0 : 1); + hdmi_config(&hdmi_info); +#ifdef __KERNEL__ + mdelay(200); /* patch for VIZIO change resolution issue */ +#endif + hdmi_cur_plugin = hdmi_check_plugin(0); + vo_hdmi_blank(vo, (vo->status & VPP_VOUT_STS_BLANK) ? + 1 : !(hdmi_cur_plugin)); + return 0; +} + +static int vo_hdmi_chkplug(struct vout_t *vo, int arg) +{ + int plugin; + + if (g_vpp.hdmi_disable) + return 0; + plugin = hdmi_get_plugin(); + DBG_DETAIL("%d\n", plugin); + return plugin; +} + +static int vo_hdmi_get_edid(struct vout_t *vo, int arg) +{ + char *buf; +#ifdef CONFIG_WMT_EDID + int i, cnt; +#endif + DBG_DETAIL("Enter\n"); + buf = (char *) arg; +#ifdef CONFIG_WMT_EDID + memset(&buf[0], 0x0, 128*EDID_BLOCK_MAX); + if (!hdmi_get_plugin()) + return 1; + + if (hdmi_DDC_read(0xA0, 0x0, &buf[0], 128)) { + DBG_ERR("read edid\n"); + return 1; + } + + if (edid_checksum(buf, 128)) { + DBG_ERR("hdmi checksum\n"); +/* g_vpp.dbg_hdmi_ddc_crc_err++; */ + return 1; + } + + cnt = buf[0x7E]; + if (cnt >= 3) + cnt = 3; + for (i = 1; i <= cnt; i++) + hdmi_DDC_read(0xA0, 0x80 * i, &buf[128 * i], 128); +#endif + return 0; +} + +struct vout_inf_t vo_hdmi_inf = { + .mode = VOUT_INF_HDMI, + .init = vo_hdmi_init, + .uninit = vo_hdmi_uninit, + .blank = vo_hdmi_blank, + .config = vo_hdmi_config, + .chkplug = vo_hdmi_chkplug, + .get_edid = vo_hdmi_get_edid, +}; + +int vo_hdmi_initial(void) +{ + vout_inf_register(VOUT_INF_HDMI, &vo_hdmi_inf); + return 0; +} +module_init(vo_hdmi_initial); + +#endif /* WMT_FTBLK_VOUT_HDMI */ + +/*--------------------------------- LVDS ------------------------------------*/ +#ifdef WMT_FTBLK_VOUT_LVDS +int vo_lvds_init_flag; +static int vo_lvds_blank(struct vout_t *vo, enum vout_blank_t arg) +{ + DBG_DETAIL("(%d)\n", arg); + if (arg == VOUT_BLANK_POWERDOWN) { + lvds_regs->test.b.tre_en = 0; + } else { /* avoid suspend signal not clear */ + lvds_set_enable((arg == VOUT_BLANK_UNBLANK) ? 1 : 0); + } + + if (vo_lvds_init_flag) + lvds_set_power_down(arg); + return 0; +} + +static int vo_lvds_config(struct vout_t *vo, int arg) +{ + DBG_DETAIL("(%d)\n", arg); + lvds_set_power_down(VPP_FLAG_DISABLE); + vo_lvds_init_flag = 1; + return 0; +} + +static int vo_lvds_init(struct vout_t *vo, int arg) +{ + DBG_DETAIL("(%d)\n", arg); + + vpp_set_clock_enable(DEV_LVDS, 1, 0); + if (vo->dev) + vo->dev->set_mode(&vo->option[0]); + govrh_set_dvo_enable(p_govrh2, 0); + govrh_set_csc_mode(vo->govr, vo->govr->fb_p->csc_mode); + lvds_set_enable((vo->status & VPP_VOUT_STS_BLANK) ? + VPP_FLAG_DISABLE : VPP_FLAG_ENABLE); + return 0; +} + +static int vo_lvds_uninit(struct vout_t *vo, int arg) +{ + DBG_DETAIL("(%d)\n", arg); + lvds_set_enable(VPP_FLAG_DISABLE); + if (vo->dev) + vo->dev->set_mode(0); + lvds_set_power_down(VPP_FLAG_ENABLE); + vpp_set_clock_enable(DEV_LVDS, 0, 0); + vo_lvds_init_flag = 0; + return 0; +} + +static int vo_lvds_chkplug(struct vout_t *vo, int arg) +{ + DBG_DETAIL("\n"); +#if 0 + vo = vout_get_info(VOUT_LVDS); + if (vo->dev) + return vo->dev->check_plugin(0); +#endif + return 1; +} + +struct vout_inf_t vo_lvds_inf = { + .mode = VOUT_INF_LVDS, + .capability = VOUT_INF_CAP_FIX_PLUG, + .init = vo_lvds_init, + .uninit = vo_lvds_uninit, + .blank = vo_lvds_blank, + .config = vo_lvds_config, + .chkplug = vo_lvds_chkplug, +#ifdef WMT_FTBLK_VOUT_HDMI + .get_edid = vo_hdmi_get_edid, +#endif +}; + +int vo_lvds_initial(void) +{ + vout_inf_register(VOUT_INF_LVDS, &vo_lvds_inf); + return 0; +} +module_init(vo_lvds_initial); + +#endif /* WMT_FTBLK_VOUT_LVDS */ +/*---------------------------------- API ------------------------------------*/ +#ifndef CFG_LOADER +int vout_set_audio(struct vout_audio_t *arg) +{ + struct vout_t *vout; + int ret = 0; + +#if 0 + vout = vout_get_info(VPP_VOUT_DVO2HDMI); + if (vout && (vout->status & VPP_VOUT_STS_PLUGIN)) { + if (vout->dev->set_audio) + vout->dev->set_audio(arg); + } +#endif + +#ifdef WMT_FTBLK_VOUT_HDMI + vout = vout_get_entry(VPP_VOUT_NUM_HDMI); + if (vout) { + g_vpp.hdmi_ch_change = 1; + hdmi_config_audio(arg); + g_vpp.hdmi_ch_change = 0; + ret = 1; + } +#endif + return ret; +} +#endif + +/* 3445 port1 : DVI/SDD, port2 : VGA/SDA, port3 : HDMI/LVDS */ +/* 3481 port1 : HDMI/LVDS, port2 : DVI */ +/* 3498 port1 : HDMI, port2 : DVI/LVDS */ +struct vout_t vout_entry_0 = { + .fix_cap = BIT(VOUT_INF_HDMI), + .option[0] = VDO_COL_FMT_ARGB, + .option[1] = VPP_DATAWIDHT_24, + .option[2] = 0, +}; + +struct vout_t vout_entry_1 = { + .fix_cap = BIT(VOUT_INF_DVI) + BIT(VOUT_INF_LVDS) + + VOUT_CAP_EXT_DEV + 0x100, /* i2c bus 1,ext dev */ + .option[0] = VDO_COL_FMT_ARGB, + .option[1] = VPP_DATAWIDHT_24, + .option[2] = 0, +}; + +int vout_add_display(int fb_no, unsigned int *parm) +{ + struct vout_info_t *info; + struct vout_t *vout; + int ret = 0; + + info = vout_info[fb_no]; + if (!info) { + info = kmalloc(sizeof(struct vout_info_t), GFP_KERNEL); + if (!info) + return 1; + memset(info, 0, sizeof(struct vout_info_t)); + vout_info[fb_no] = info; + DBG_MSG("malloc vout_info %d,0x%x\n", fb_no, (int) info); +#ifdef CONFIG_KERNEL + sema_init(&info->sem, 1); +#endif + } + + if (parm[0] == VOUT_BOOT) { + struct vout_t *vo_boot; + + MSG("[VOUT] %s (%d:%d:%d)\n", + (fb_no == 0) ? "tvbox" : "virtual display", + parm[0], parm[1], parm[2]); + if (fb_no == 0) { + g_vpp.virtual_display = 1; + g_vpp.fb0_bitblit = 1; + } else { + g_vpp.stream_fb = fb_no; + } + vo_boot = kmalloc(sizeof(struct vout_t), GFP_KERNEL); + if (vo_boot == 0) + return 1; + memset(vo_boot, 0, sizeof(struct vout_t)); + vo_boot->resx = parm[3]; + vo_boot->resy = parm[4]; + vo_boot->fps = parm[5]; + vo_boot->num = VPP_VOUT_NUM; + vout_info_add_entry(fb_no, vo_boot); + kfree(vo_boot); + return 0; + } + + vout = vout_get_entry_adapter(parm[0]); + vout->inf = vout_get_inf_entry_adapter(parm[0]); + vout->option[0] = parm[1]; + vout->option[1] = parm[2]; + vout->resx = parm[3]; + vout->resy = parm[4]; + vout->fps = parm[5]; + vout->disable = (parm[2] & VOUT_OPT_BLANK) ? 1 : 0; + switch (parm[0]) { + case VOUT_LVDS: + { + struct fb_videomode *vmode = 0; + + /* lvds auto detect edid */ + if ((parm[1] == 0) && (parm[3] == 0) && (parm[4] == 0)) { + if (vout_get_edid_option(vout->num)) { + vmode = &vout->edid_info.detail_timing[0]; + if (vmode->pixclock == 0) { + vmode = 0; + DBG_ERR("LVDS timing\n"); + } + } + + if (vout->inf->get_edid(vout, (int)vout->edid) == 0) { + if (edid_parse(vout->edid, + &vout->edid_info) == 0) + DBG_ERR("LVDS edid parse\n"); + } else { + DBG_ERR("LVDS edid read\n"); + } + } + + if (vmode == 0) { /* use internal timing */ + struct lcd_parm_t *p = 0; + + if (parm[1]) { + p = lcd_get_parm(parm[1], parm[2]); + if (p) + lcd_set_lvds_id(parm[1]); + } + + if (p == 0) + p = lcd_get_oem_parm(parm[3], parm[4]); + vmode = &p->vmode; + } + vout->option[2] = vmode->vmode; + info->resx = vmode->xres; + info->resy = vmode->yres; + info->fps = vmode->refresh; + vout_info_set_fixed_timing(fb_no, vmode); + lcd_set_type(1); + } + case VOUT_LCD: + { + struct vout_dev_t *dev; + + lcd_set_parm(parm[1], parm[2] & 0xFF); + dev = lcd_get_dev(); + vout->dev = dev; + dev->vout = vout; + vout->option[0] = VDO_COL_FMT_ARGB; + vout->option[1] &= ~0xFF; + vout->option[1] |= VPP_DATAWIDHT_24; + vout->dev->init(vout); + vout_info_set_fixed_timing(fb_no, &p_lcd->vmode); + } + break; + case VOUT_DVI: + { + struct vout_dev_t *dev = 0; + + g_vpp.dvi_int_disable = + (parm[2] & WMT_DISP_FB_DISBALE_DVI_INT) ? 1 : 0; + g_vpp.dvi_int_no = (parm[2] & WMT_DISP_FB_DVI_INT) ? + ((parm[1] & 0xF000) >> 12) : VPP_DVI_INT_DEFAULT; + g_vpp.dvi_i2c_no = (parm[2] & WMT_DISP_FB_DVI_I2C) ? + ((parm[1] & 0xF00) >> 8) : VPP_DVI_I2C_DEFAULT; + g_vpp.dvi_i2c_no &= VPP_DVI_I2C_ID_MASK; + + if (parm[2] & WMT_DISP_FB_DISABLE_EXTDEV) + vout->dev = 0; + else { + vpp_i2c_init(VPP_DVI_I2C_ID, 0xA0); + do { + dev = vout_get_device(dev); + if (dev == 0) + break; + if (vout->fix_cap & BIT(dev->mode)) { + vout->inf = + vout_inf_get_entry(dev->mode); + if (dev->init(vout) == 0) { + vout->dev = dev; + dev->vout = vout; + break; + } + } + } while (1); + } + + DBG_MSG("DVI ext dev : %s\n", + (vout->dev) ? vout->dev->name : "NO"); + } + info->option = (parm[2] & WMT_DISP_FB_INTERLACE) ? + VPP_OPT_INTERLACE : 0; + break; + case VOUT_HDMI: + info->option = (parm[2] & WMT_DISP_FB_INTERLACE) ? + VPP_OPT_INTERLACE : 0; +#if 0 /* use old uboot param and wait next chip */ + g_vpp.hdmi_disable = + (parm[2] & WMT_DISP_FB_HDMI_DISABLE) ? 1 : 0; + + g_vpp.hdmi_sp_mode = + (parm[2] & WMT_DISP_FB_HDMI_SP_MODE) ? 1 : 0; +#endif + break; + default: + break; + } + + if (ret == 0) + vout_info_add_entry(fb_no, vout); + return ret; +} + +int vout_check_display(void) +{ + #define BUF_LEN 100 + char buf[BUF_LEN]; + int varlen = BUF_LEN; + unsigned int parm[32]; + int i, idx; + + if (wmt_getsyspara("wmt.display.fb0", buf, &varlen)) { + /* default for no uboot parameter */ + parm[0] = VOUT_HDMI; + parm[1] = VDO_COL_FMT_ARGB; + parm[2] = VPP_DATAWIDHT_24; + parm[3] = 1280; + parm[4] = 720; + parm[5] = 60; + vout_add_display(0, &parm[0]); + parm[0] = VOUT_DVI; + parm[1] = VDO_COL_FMT_ARGB; + parm[2] = VPP_DATAWIDHT_24; + parm[3] = 1024; + parm[4] = 768; + parm[5] = 60; + vout_add_display(0, &parm[0]); + return 1; + } else { + int fb_no = 0; + int num; + + while (fb_no < VPP_VOUT_INFO_NUM) { + sprintf(buf, "wmt.display.fb%d", fb_no); + varlen = BUF_LEN; + if (wmt_getsyspara(buf, buf, &varlen)) + break; + + DBG_DETAIL("fb%d : %s\n", fb_no, buf); + varlen = vpp_parse_param(buf, + (unsigned int *)parm, 32, 0x1C1C1C1D); + DBG_DETAIL("op 0x%x\n", parm[0]); + num = (varlen - 1) / 7; + for (i = 0; i < num; i++) { + idx = 1 + 8 * i; /* [ + 6 + ] = 8 */ + DBG_DETAIL("%d : %x, %x, %x (%dx%d@%d)\n", i, + parm[idx + 1], parm[idx + 2], + parm[idx + 3], parm[idx + 4], + parm[idx + 5], parm[idx + 6]); + vout_add_display(fb_no, &parm[idx + 1]); + } + + vout_info[fb_no]->multi = + (parm[0] & WMT_DISP_FB_MULTI) ? 1 : 0; + vout_info[fb_no]->alloc_mode = (parm[0] & 0xF); + vout_info[fb_no]->hwc_mode = (parm[0] & 0xF0) >> 4; + if (parm[0] & WMT_DISP_FB_COLFMT) + vout_info[fb_no]->fb.col_fmt = ((parm[0] & + WMT_DISP_FB_COLFMT_MASK) >> 16); + fb_no++; + } + } + + /* [uboot parameter] oem timing : + pixclk:option:hsync:hbp:hpixel:hfp:vsync:vbp:vpixel:vfp */ + varlen = BUF_LEN; + if (wmt_getsyspara("wmt.display.tmr", buf, &varlen) == 0) { + struct fb_videomode *p; + int xres, yres; + struct fb_videomode vo_oem_vmode; + + p = &vo_oem_vmode; + DBG_MSG("tmr %s\n", buf); + vpp_parse_param(buf, parm, 12, 0); + p->pixclock = parm[0]; + p->vmode = parm[1]; + p->hsync_len = parm[2]; + p->left_margin = parm[3]; + p->xres = parm[4]; + p->right_margin = parm[5]; + p->vsync_len = parm[6]; + p->upper_margin = parm[7]; + p->yres = parm[8]; + p->lower_margin = parm[9]; + p->pixclock *= 1000; + xres = p->hsync_len + p->left_margin + p->xres + + p->right_margin; + yres = p->vsync_len + p->upper_margin + p->yres + + p->lower_margin; + p->refresh = vpp_calc_refresh(p->pixclock, xres, yres); + if (p->refresh == 59) + p->refresh = 60; + p->vmode = (parm[1] & VPP_OPT_INTERLACE) ? FB_VMODE_INTERLACED : 0; + p->sync = (parm[1] & VPP_DVO_SYNC_POLAR_HI) ? FB_SYNC_HOR_HIGH_ACT : 0; + p->sync |= (parm[1] & VPP_DVO_VSYNC_POLAR_HI) ? FB_SYNC_VERT_HIGH_ACT : 0; + DBG_MSG("tmr pixclk %d,option 0x%x\n", + p->pixclock, p->vmode); + DBG_MSG("H sync %d,bp %d,pixel %d,fp %d\n", p->hsync_len, + p->left_margin, p->xres, p->right_margin); + DBG_MSG("V sync %d,bp %d,pixel %d,fp %d\n", p->vsync_len, + p->upper_margin, p->yres, p->lower_margin); + p->pixclock = KHZ2PICOS(p->pixclock / 1000); + vout_info_set_fixed_timing(0, &vo_oem_vmode); + vout_info[0]->fixed_width = parm[10]; + vout_info[0]->fixed_height = parm[11]; + vout_info[0]->resx = p->xres; + vout_info[0]->resy = p->yres; + vout_info[0]->fps = p->refresh; + vout_info[0]->vout[0]->resx = p->xres; + vout_info[0]->vout[0]->resy = p->yres; + vout_info[0]->vout[0]->fps = p->refresh; + } + return 0; +} + +int vout_init(void) +{ + struct vout_info_t *info; + struct vout_t *vout; + int i, j; + + DBG_DETAIL("Enter\n"); + + for(i = 0; i < VPP_VOUT_INFO_NUM; i++) { + if(vout_info[i] != NULL) { + kfree(vout_info[i]); + vout_info[i] = NULL; + } + } + + /* register vout & set default */ + vout_register(0, &vout_entry_0); + vout_entry_0.inf = vout_inf_get_entry(VOUT_INF_HDMI); + vout_entry_0.govr = p_govrh; + vout_register(1, &vout_entry_1); + vout_entry_1.inf = vout_inf_get_entry(VOUT_INF_DVI); + vout_entry_1.govr = p_govrh2; + + /* check vout info */ + DBG_DETAIL("check display\n"); + vout_check_display(); + + /* initial vout */ + DBG_DETAIL("init display\n"); + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + info = vout_info[i]; + if (!info) + break; + for (j = 0; ; j++) { + vout = info->vout[j]; + if (vout == 0) + break; + if (vout->inf) + vout->inf->init(vout, 0); + } + } + + /* check monitor resolution */ + DBG_DETAIL("check resolution\n"); + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + struct vout_t *vout_first = 0; + struct vout_t *vout_plug = 0; + + info = vout_info[i]; + if (!info) + break; + for (j = 0; ; j++) { + vout = info->vout[j]; + if (vout == 0) + break; + + if (vout_first == 0) /* first priority */ + vout_first = vout; + + if (vout_chkplug(vout->num)) { + struct fb_videomode vmode; + + vmode.xres = vout->resx; + vmode.yres = vout->resy; + vmode.refresh = vout->fps; + vmode.vmode = 0; + vout_find_match_mode(i, &vmode, 1); + vout->resx = vmode.xres; + vout->resy = vmode.yres; + vout->fps = vmode.refresh; + if (vout_plug == 0) /* first plugin */ + vout_plug = vout; + } + + if (info->multi) + vout_change_status(vout, + VPP_VOUT_STS_ACTIVE, 1); + } + + vout = (vout_plug) ? vout_plug : vout_first; + if (vout) { + vout_change_status(vout, VPP_VOUT_STS_ACTIVE, 1); + info->resx = vout->resx; + info->resy = vout->resy; + info->fps = vout->fps; + } + } + +#ifdef DEBUG + /* show display info */ + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + info = vout_info[i]; + if (!info) + break; + MSG("-----------------------------------------------------\n"); + MSG("fb%d, resx %d,resy %d,fps %d\n", i, + info->resx, info->resy, info->fps); + MSG("resx_vir %d,resy_vir %d,pixclk %d\n", info->resx_virtual, + info->resy_virtual, info->pixclk); + MSG("multi %d,alloc %d,option 0x%x\n", info->multi, + info->alloc_mode, info->option); + + for (j = 0; ; j++) { + vout = info->vout[j]; + if (vout == 0) + break; + vout_print_entry(vout); + } + } + MSG("-----------------------------------------------------\n"); +#endif + DBG_DETAIL("Leave\n"); + return 0; +} + +int vout_exit(void) +{ + return 0; +} diff --git a/common/wmt_display/vout.c b/common/wmt_display/vout.c new file mode 100755 index 0000000..9291ac5 --- /dev/null +++ b/common/wmt_display/vout.c @@ -0,0 +1,941 @@ +/*++ + * linux/drivers/video/wmt/vout.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define VOUT_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "vout.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ +/* #define VO_XXXX xxxx *//*Example*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define VO_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx vo_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in vout.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int vo_xxx; *//*Example*/ +struct vout_t *vout_array[VPP_VOUT_NUM]; +struct vout_inf_t *vout_inf_array[VOUT_INF_MODE_MAX]; +struct vout_dev_t *vout_dev_list; + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void vo_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +/*----------------------- vout API --------------------------------------*/ +void vout_register(int no, struct vout_t *vo) +{ + if (no >= VPP_VOUT_NUM) + return; + + vo->num = no; + vo->govr = (void *) p_govrh; + vo->status = VPP_VOUT_STS_REGISTER; + vo->info = 0; + vout_array[no] = vo; +} + +struct vout_t *vout_get_entry(int no) +{ + if (no >= VPP_VOUT_NUM) + return 0; + return vout_array[no]; +} +EXPORT_SYMBOL(vout_get_entry); + +struct vout_info_t *vout_get_info_entry(int no) +{ + struct vout_info_t *info; + struct vout_t *vout; + int i, j; + + if (no >= VPP_VOUT_NUM) + return 0; + + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + info = vout_info[i]; + if (!info) + break; + for (j = 0; j < VPP_VOUT_NUM; j++) { + vout = info->vout[j]; + if (vout == 0) + break; + if (vout->num == no) + return info; + } + } + return 0; +} + +void vout_change_status(struct vout_t *vo, int mask, int sts) +{ + DBG_DETAIL("(0x%x,%d)\n", mask, sts); + if (sts) + vo->status |= mask; + else + vo->status &= ~mask; + + switch (mask) { + case VPP_VOUT_STS_PLUGIN: + if (sts == 0) { + vo->status &= ~(VPP_VOUT_STS_EDID + + VPP_VOUT_STS_CONTENT_PROTECT); + vo->edid_info.option = 0; +#ifdef __KERNEL__ + vpp_netlink_notify_cp(0); +#endif + } + break; + default: + break; + } +} + +int vout_query_inf_support(int no, enum vout_inf_mode_t mode) +{ + struct vout_t *vo; + + if (no >= VPP_VOUT_NUM) + return 0; + + if (mode >= VOUT_INF_MODE_MAX) + return 0; + + vo = vout_get_entry(no); + return (vo->fix_cap & BIT(mode)) ? 1 : 0; +} + +/*----------------------- vout interface API --------------------------------*/ +int vout_inf_register(enum vout_inf_mode_t mode, struct vout_inf_t *inf) +{ + if (mode >= VOUT_INF_MODE_MAX) { + DBG_ERR("vout interface mode invalid %d\n", mode); + return -1; + } + + if (vout_inf_array[mode]) + DBG_ERR("vout interface register again %d\n", mode); + + vout_inf_array[mode] = inf; + return 0; +} /* End of vout_register */ + +struct vout_inf_t *vout_inf_get_entry(enum vout_inf_mode_t mode) +{ + if (mode >= VOUT_INF_MODE_MAX) { + DBG_ERR("vout interface mode invalid %d\n", mode); + return 0; + } + return vout_inf_array[mode]; +} + +/*----------------------- vout device API -----------------------------------*/ +int vout_device_register(struct vout_dev_t *ops) +{ + struct vout_dev_t *list; + + if (vout_dev_list == 0) { + vout_dev_list = ops; + list = ops; + } else { + list = vout_dev_list; + while (list->next != 0) + list = list->next; + list->next = ops; + } + ops->next = 0; + return 0; +} + +struct vout_dev_t *vout_get_device(struct vout_dev_t *ops) +{ + if (ops == 0) + return vout_dev_list; + return ops->next; +} + +struct vout_t *vout_get_entry_adapter(enum vout_mode_t mode) +{ + int no; + + switch (mode) { + case VOUT_SD_DIGITAL: + case VOUT_DVI: + case VOUT_LCD: + case VOUT_DVO2HDMI: + case VOUT_SD_ANALOG: + case VOUT_VGA: + no = VPP_VOUT_NUM_DVI; + break; + case VOUT_HDMI: + no = VPP_VOUT_NUM_HDMI; + break; + case VOUT_LVDS: + no = VPP_VOUT_NUM_LVDS; + break; + default: + no = VPP_VOUT_NUM; + break; + } + return vout_get_entry(no); +} + +struct vout_inf_t *vout_get_inf_entry_adapter(enum vout_mode_t mode) +{ + int no; + + switch (mode) { + case VOUT_SD_DIGITAL: + case VOUT_SD_ANALOG: + case VOUT_DVI: + case VOUT_LCD: + case VOUT_DVO2HDMI: + case VOUT_VGA: + no = VOUT_INF_DVI; + break; + case VOUT_HDMI: + no = VOUT_INF_HDMI; + break; + case VOUT_LVDS: + no = VOUT_INF_LVDS; + break; + default: + no = VOUT_INF_MODE_MAX; + return 0; + } + return vout_inf_get_entry(no); +} + +enum vpp_vout_s vout_get_mode_adapter(struct vout_t *vout) +{ + enum vpp_vout_s mode; + + switch (vout->inf->mode) { + case VOUT_INF_DVI: + mode = VPP_VOUT_DVI; + if (vout->dev && (strcmp("LCD", vout->dev->name) == 0)) + mode = VPP_VOUT_LCD; + break; + case VOUT_INF_HDMI: + mode = VPP_VOUT_HDMI; + break; + case VOUT_INF_LVDS: + mode = VPP_VOUT_LVDS; + break; + default: + mode = VPP_VOUT_NONE; + break; + } + return mode; +} + +int vout_info_add_entry(int no, struct vout_t *vo) +{ + struct vout_info_t *info; + int i = 0; + + if ((vo == 0) || (vo->info)) + return 0; + + info = vout_info[no]; + info->num = no; + if (vo->num < VPP_VOUT_NUM) { /* not virtual vout */ + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (info->vout[i] == 0) { + info->vout[i] = vo; + vo->info = info; + break; + } else { + if (info->vout[i] == vo) /* exist */ + break; + } + } + } + + if (i == 0) { /* new */ + info->resx = vo->resx; + info->resy = vo->resy; + info->resx_virtual = vpp_calc_align(info->resx, 4); + info->resy_virtual = info->resy; + info->fps = (int) vo->fps; + DBG_MSG("new %dx%d@%d\n", info->resx, info->resy, info->fps); + } + + DBG_MSG("info %d,%dx%d@%d\n", no, info->resx, info->resy, info->fps); + return no; +} + +struct vout_info_t *vout_info_get_entry(int no) +{ + if (no >= VPP_VOUT_INFO_NUM) + return 0; + return vout_info[no]; +} + +void vout_info_set_fixed_timing(int no, struct fb_videomode *vmode) +{ + struct vout_info_t *info; + + DBG_MSG("(%d)\n", no); + + info = vout_info_get_entry(no); + if (!info->fixed_vmode) { + info->fixed_vmode = + kmalloc(sizeof(struct fb_videomode), GFP_KERNEL); + if (!info->fixed_vmode) + return; + } + memcpy(info->fixed_vmode, vmode, sizeof(struct fb_videomode)); +} + +struct govrh_mod_t *vout_info_get_govr(int no) +{ + struct vout_info_t *info; + struct govrh_mod_t *govr = 0; + int i; + + info = vout_info[no]; + if (!info) + return 0; + + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (info->vout[i]) { + if (govr == 0) + govr = info->vout[i]->govr; + if (info->vout[i]->status & VPP_VOUT_STS_ACTIVE) { + govr = info->vout[i]->govr; + break; + } + } + } + return govr; +} + +int vout_check_ratio_16_9(unsigned int resx, unsigned int resy) +{ + int val; + + val = (resy) ? ((resx * 10) / resy) : 0; + return (val >= 15) ? 1 : 0; +} + +struct fb_videomode *vout_get_video_mode(int vout_num, + struct fb_videomode *vmode, int option) +{ + int i; + struct fb_videomode *p, *best = NULL; + unsigned int diff = -1, diff_refresh = -1; + int d; + int resx, resy, fps; + unsigned int pixel_clock, diff_pixel_clock = -1; + struct vout_t *vo = 0; + char *edid = 0; + + resx = vmode->xres; + resy = vmode->yres; + fps = vmode->refresh; +#ifdef DEBUG + pixel_clock = (vmode->pixclock) ? PICOS2KHZ(vmode->pixclock) * 1000 : 0; + DBG_MSG("%d,%dx%d@%d,%d,0x%x\n", vout_num, resx, resy, fps, + pixel_clock, option); +#endif + pixel_clock = vmode->pixclock; + + /* EDID detail timing */ + if (option & VOUT_MODE_OPTION_EDID) { + unsigned int opt; + struct fb_videomode *edid_vmode; + + vo = vout_get_entry(vout_num); + if (vo == 0) + return 0; + + edid = vout_get_edid(vout_num); + if (edid_parse(edid, &vo->edid_info)) { + opt = fps | ((option & + VOUT_MODE_OPTION_INTERLACE) ? + EDID_TMR_INTERLACE : 0); + if (edid_find_support(&vo->edid_info, + resx, resy, opt, &edid_vmode)) { + if (edid_vmode) { + DBG_MSG("EDID detail timing\n"); + return edid_vmode; + } + } + } + } + + /* video mode table */ + for (i = 0; ; i++) { + p = (struct fb_videomode *) &vpp_videomode[i]; + if (p->pixclock == 0) + break; + + if (option & VOUT_MODE_OPTION_LESS) { + if ((p->xres > resx) || (p->yres > resy)) + continue; + } + if (option & VOUT_MODE_OPTION_GREATER) { + if ((p->xres < resx) || (p->yres < resy)) + continue; + } + if (option & VOUT_MODE_OPTION_INTERLACE) { + if (!(p->vmode & FB_VMODE_INTERLACED)) + continue; + } + if (option & VOUT_MODE_OPTION_PROGRESS) { + if ((p->vmode & FB_VMODE_INTERLACED)) + continue; + } + if ((option & VOUT_MODE_OPTION_EDID) && + (edid_parse(edid, &vo->edid_info))) { + unsigned int opt; + struct fb_videomode *edid_vmode; + + opt = p->refresh | ((option & + VOUT_MODE_OPTION_INTERLACE) ? + EDID_TMR_INTERLACE : 0); + if (edid_find_support(&vo->edid_info, + p->xres, p->yres, opt, &edid_vmode)) { + if (edid_vmode) + p = edid_vmode; + } else { + continue; + } + } + d = abs(p->xres - resx) + abs(p->yres - resy); + d = abs(d); + if (diff > d) { + diff = d; + diff_refresh = abs(p->refresh - fps); + diff_pixel_clock = abs(p->pixclock - pixel_clock); + best = p; + } else if (diff == d) { + d = abs(p->refresh - fps); + if (diff_refresh > d) { + diff_refresh = d; + diff_pixel_clock = + abs(p->pixclock - pixel_clock); + best = p; + } else if (diff_refresh == d) { + d = abs(p->pixclock - pixel_clock); + if (diff_pixel_clock > d) { + diff_pixel_clock = d; + best = p; + } + } + } + } + if (best) + DBG_MSG("%dx%d@%d\n", best->xres, best->yres, best->refresh); + return best; +} + +int vout_get_width_height(int fbnum, int *width, int *height) +{ + struct vout_info_t *info; + int i; + + info = vout_info_get_entry(fbnum); + *width = 0; + *height = 0; + for (i = 0; i < VPP_VOUT_NUM; i++) { + struct vout_t *vout; + + vout = info->vout[i]; + if (vout) { + if ((vout->inf->mode == VOUT_INF_DVI) && p_lcd) { + if (info->fixed_width != 0 && info->fixed_height != 0) { + *width = info->fixed_width; + *height = info->fixed_height; + } else { + *width = p_lcd->width; + *height = p_lcd->height; + } + break; + } + if (vout_chkplug(vout->num)) { + if (vout_get_edid_option(vout->num) + & EDID_OPT_VALID) { + *width = vout->edid_info.width; + *height = vout->edid_info.height; + break; + } + } + } + } + return 0; +} + +#ifndef CONFIG_VPOST +int vout_find_match_mode(int fbnum, + struct fb_videomode *vmode, int match) +{ + struct vout_info_t *info; + struct fb_videomode *p; + int no = VPP_VOUT_NUM; + unsigned int option; + int i; + + DBG_DETAIL("(%d)\n", fbnum); + + info = vout_info_get_entry(fbnum); + if (vmode->refresh == 59) + vmode->refresh = 60; + + /* fixed timing */ + if (info->fixed_vmode) { + if (info->fixed_vmode->xres != vmode->xres) + return -1; + if (info->fixed_vmode->yres != vmode->yres) + return -1; + if (info->fixed_vmode->refresh != vmode->refresh) + return -1; + p = info->fixed_vmode; + goto label_find_match; + } + for (i = 0; i < VPP_VOUT_NUM; i++) { + if (info->vout[i]) { + int vout_no = info->vout[i]->num; + + if (no == VPP_VOUT_NUM) + no = vout_no; /* get first vo */ + if (vout_chkplug(vout_no)) { + no = vout_no; + break; + } + } + } + /* resolution match and interlace match */ + option = VOUT_MODE_OPTION_GREATER + VOUT_MODE_OPTION_LESS; + option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID; + option |= (vmode->vmode & FB_VMODE_INTERLACED) ? + VOUT_MODE_OPTION_INTERLACE : VOUT_MODE_OPTION_PROGRESS; + p = vout_get_video_mode(no, vmode, option); + if (p) + goto label_find_match; + + /* resolution match but interlace not match */ + option = VOUT_MODE_OPTION_GREATER + VOUT_MODE_OPTION_LESS; + option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID; + option |= (vmode->vmode & FB_VMODE_INTERLACED) ? + VOUT_MODE_OPTION_PROGRESS : VOUT_MODE_OPTION_INTERLACE; + p = vout_get_video_mode(no, vmode, option); + if (p) + goto label_find_match; + +/* if( !match ){ */ + /* resolution less best mode */ + option = VOUT_MODE_OPTION_LESS; + option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID; + p = vout_get_video_mode(no, vmode, option); + if (p) + goto label_find_match; +/* } */ + DBG_ERR("no support mode\n"); + return -1; +label_find_match: + *vmode = *p; +#ifdef CONFIG_UBOOT + info->p_vmode = p; +#endif + return 0; +} +#endif + +int vout_find_edid_support_mode( + struct edid_info_t *info, + unsigned int *resx, + unsigned int *resy, + unsigned int *fps, + int r_16_9 +) +{ + /* check the EDID to find one that not large and same ratio mode*/ +#ifdef CONFIG_WMT_EDID + int i, cnt; + struct fb_videomode *p; + unsigned int w, h, f, option; + + if ((*resx == 720) && (*resy == 480) && (*fps == 50)) + *fps = 60; + + for (i = 0, cnt = 0; ; i++) { + if (vpp_videomode[i].pixclock == 0) + break; + cnt++; + } + + for (i = cnt - 1; i >= 0; i--) { + p = (struct fb_videomode *) &vpp_videomode[i]; + h = p->yres; + if (h > *resy) + continue; + + w = p->xres; + if (w > *resx) + continue; + + f = p->refresh; + if (f > *fps) + continue; + + if (r_16_9 != vout_check_ratio_16_9(w, h)) + continue; + + option = f & EDID_TMR_FREQ; + option |= (p->vmode & FB_VMODE_INTERLACED) ? + EDID_TMR_INTERLACE : 0; + + if (edid_find_support(info, w, h, option, &p)) { + *resx = w; + *resy = h; + *fps = f; + DBG_MSG("(%dx%d@%d)\n", w, h, f); + return 1; + } + } +#endif + return 0; +} + +/*----------------------- vout control API ----------------------------------*/ +void vout_set_framebuffer(struct vout_info_t *info, vdo_framebuf_t *fb) +{ + int i; + struct vout_t *vo; + + if (!info) + return; + + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = info->vout[i]; + if (vo == 0) + break; + if (vo->govr) + vo->govr->fb_p->set_framebuf(fb); + } +} + +int vout_set_blank(int no, enum vout_blank_t arg) +{ + struct vout_t *vo; + + DBG_DETAIL("(%d,%d)\n", no, arg); + + vo = vout_get_entry(no); + if (vo && (vo->inf)) { + vout_change_status(vo, VPP_VOUT_STS_BLANK, arg); + vo->inf->blank(vo, arg); + if (vo->dev && vo->dev->set_power_down) + vo->dev->set_power_down( + (arg == VOUT_BLANK_POWERDOWN) ? 1 : 0); + if (vo->govr) + govrh_set_MIF_enable(vo->govr, (arg) ? 0 : 1); + } + return 0; +} + +int vout_set_mode(int no, enum vout_inf_mode_t mode) +{ + struct vout_t *vo; + + DBG_DETAIL("(%d,%d)\n", no, mode); + + if (vout_query_inf_support(no, mode) == 0) { + DBG_ERR("not support this interface(%d,%d)\n", no, mode); + return -1; + } + + vo = vout_get_entry(no); + if (vo->inf) { + if (vo->inf->mode == mode) + return 0; + vo->inf->uninit(vo, 0); + vout_change_status(vo, VPP_VOUT_STS_ACTIVE, 0); + if (vo->dev) + vo->dev->set_power_down(1); + } + + vo->inf = vout_inf_get_entry(mode); + vo->inf->init(vo, 0); + vout_change_status(vo, VPP_VOUT_STS_ACTIVE, 1); + return 0; +} + +int vout_config(struct vout_info_t *info, struct fb_videomode *vmode, + vdo_framebuf_t *fb) +{ + struct vout_t *vo; + int i; + + DBG_DETAIL("\n"); + + if (!vmode && !fb) + return 0; + + if (vmode) { + /* option for interface & device config */ + info->resx = vmode->xres; + info->resy = vmode->yres; + info->fps = (vmode->refresh == 59) ? 60 : vmode->refresh; + info->option = (vmode->vmode & FB_VMODE_INTERLACED) ? + VPP_OPT_INTERLACE : 0; + info->option |= (vmode->sync & FB_SYNC_HOR_HIGH_ACT) ? + VPP_DVO_SYNC_POLAR_HI : 0; + info->option |= (vmode->sync & FB_SYNC_VERT_HIGH_ACT) ? + VPP_DVO_VSYNC_POLAR_HI : 0; + } + + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = info->vout[i]; + if (vo == 0) + break; + + if (vo->govr == 0) + continue; + + if (vmode) { + govrh_set_videomode(vo->govr, vmode); + + if (vo->inf) { + vo->inf->config(vo, (int)info); + if (vo->dev) + vo->dev->config(info); + } + } + + if (fb) + govrh_set_framebuffer(vo->govr, fb); + } + return 0; +} + +int vout_chkplug(int no) +{ + struct vout_t *vo; + struct vout_inf_t *inf; + int ret = 0; + + DBG_DETAIL("(%d)\n", no); + + vo = vout_get_entry(no); + if (vo == 0) + return 0; + + if (vo->inf == 0) + return 0; + + inf = vout_inf_get_entry(vo->inf->mode); + if (inf == 0) + return 0; + + if (vo->dev && vo->dev->check_plugin) + ret = vo->dev->check_plugin(0); + else + ret = inf->chkplug(vo, 0); + vout_change_status(vo, VPP_VOUT_STS_PLUGIN, ret); + return ret; +} + +int vout_inf_chkplug(int no, enum vout_inf_mode_t mode) +{ + struct vout_t *vo; + struct vout_inf_t *inf; + int plugin = 0; + + DBG_MSG("(%d,%d)\n", no, mode); + if (vout_query_inf_support(no, mode) == 0) + return 0; + + vo = vout_get_entry(no); + inf = vout_inf_get_entry(mode); + if (inf) { + if (inf->chkplug) + plugin = inf->chkplug(vo, 0); + } + return plugin; +} + +char *vout_get_edid(int no) +{ + struct vout_t *vo; + int ret; + + DBG_DETAIL("(%d)\n", no); + + if (edid_disable) + return 0; + vo = vout_get_entry(no); + if (vo == 0) + return 0; + + if (vo->status & VPP_VOUT_STS_EDID) { + DBG_MSG("edid exist\n"); + return vo->edid; + } + + vout_change_status(vo, VPP_VOUT_STS_EDID, 0); +#ifdef CONFIG_VOUT_EDID_ALLOC + if (vo->edid == 0) { + vo->edid = kmalloc(128 * EDID_BLOCK_MAX, GFP_KERNEL); + if (!vo->edid) { + DBG_ERR("edid buf alloc\n"); + return 0; + } + } +#endif + + ret = 1; + if (vo->dev && vo->dev->get_edid) { + ret = vo->dev->get_edid(vo->edid); + } else { + if (vo->inf->get_edid) + ret = vo->inf->get_edid(vo, (int)vo->edid); + } + + if (ret == 0) { + DBG_DETAIL("edid read\n"); + vout_change_status(vo, VPP_VOUT_STS_EDID, 1); + return vo->edid; + } else { + DBG_MSG("read edid fail\n"); + } + +#ifdef CONFIG_VOUT_EDID_ALLOC + kfree(vo->edid); + vo->edid = 0; +#endif + return 0; +} + +int vout_get_edid_option(int no) +{ + struct vout_t *vo; + + DBG_DETAIL("(%d)\n", no); + + vo = vout_get_entry(no); + if (vo == 0) + return 0; + + if (vo->edid_info.option) + return vo->edid_info.option; + + if (vout_get_edid(no) == 0) { + if (no == VPP_VOUT_NUM_HDMI) { /* HDMI wo EDID still can work */ + vo->edid_info.option = (EDID_OPT_HDMI + EDID_OPT_AUDIO); + return vo->edid_info.option; + } + return 0; + } + + edid_parse(vo->edid, &vo->edid_info); + return vo->edid_info.option; +} + +unsigned int vout_get_mask(struct vout_info_t *vo_info) +{ + unsigned int mask; + int i; + + if (g_vpp.virtual_display) { + if (vo_info->num == 0) + return 0; + return VPP_VOUT_ALL; + } + + mask = 0; + for (i = 0; i <= VPP_VOUT_NUM; i++) { + if (vo_info->vout[i] == 0) + break; + mask |= (0x1 << vo_info->vout[i]->num); + } + return mask; +} + +int vout_check_plugin(int clr_sts) +{ + struct vout_t *vo; + int i; + int plugin = 0; + + for (i = 0; i <= VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (vo == 0) + continue; + if (vo->inf == 0) + continue; + + if (vo->dev) { + if (!(vo->dev->capability & VOUT_DEV_CAP_FIX_PLUG)) { + if (vout_chkplug(i)) { + plugin = 1; + if (clr_sts) + vout_change_status(vo, + VPP_VOUT_STS_PLUGIN, 0); + DBG_MSG("[VPP] ext dev plugin\n"); + } + } + } else { + if (!(vo->inf->capability & VOUT_INF_CAP_FIX_PLUG)) { + if (vout_chkplug(i)) { + plugin = 1; + if (clr_sts) + vout_change_status(vo, + VPP_VOUT_STS_PLUGIN, 0); + DBG_MSG("[VPP] inf dev plugin\n"); + } + } + } + } + return plugin; +} + +enum vout_tvformat_t vout_get_tvformat(void) +{ + char buf[40] = {0}; + int varlen = 40; + enum vout_tvformat_t s_tvformat = TV_MAX; + + if (wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) { + if (!strnicmp(buf, "PAL", 3)) + s_tvformat = TV_PAL; + else if (!strnicmp(buf, "NTSC", 4)) + s_tvformat = TV_NTSC; + else + s_tvformat = TV_UNDEFINED; + } else + s_tvformat = TV_UNDEFINED; + + return s_tvformat; +} + +/*--------------------End of Function Body -----------------------------------*/ +#undef VOUT_C diff --git a/common/wmt_display/vout.h b/common/wmt_display/vout.h new file mode 100755 index 0000000..d6dbcb6 --- /dev/null +++ b/common/wmt_display/vout.h @@ -0,0 +1,391 @@ +/*++ + * linux/drivers/video/wmt/vout.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef VOUT_H +/* To assert that only one occurrence is included */ +#define VOUT_H +/*-------------------- MODULE DEPENDENCY -------------------------------------*/ +#include "vpp.h" +#include "sw_i2c.h" +#include "edid.h" + +/* following is the C++ header */ +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +/* #define VO_XXXX 1 *//*Example*/ +/* #define CONFIG_VOUT_EDID_ALLOC */ +#define CONFIG_VOUT_REFACTORY + +#define VOUT_INFO_DEFAULT_RESX 1024 +#define VOUT_INFO_DEFAULT_RESY 768 +#define VOUT_INFO_DEFAULT_FPS 60 + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void vo_xxx_t; *//*Example*/ + +enum vout_mode_t { + VOUT_SD_ANALOG, + VOUT_SD_DIGITAL, + VOUT_LCD, + VOUT_DVI, + VOUT_HDMI, + VOUT_DVO2HDMI, + VOUT_LVDS, + VOUT_VGA, + VOUT_BOOT, + VOUT_MODE_MAX, + VOUT_MODE_ALL = VOUT_MODE_MAX +}; + +enum vout_dev_mode_t { + VOUT_DEV_VGA, + VOUT_DEV_DVI, + VOUT_DEV_LCD, + VOUT_DEV_HDMI, + VOUT_DEV_SDD, + VOUT_DEV_LVDS, + VOUT_DEV_MODE_MAX +}; + +enum vout_inf_mode_t { + VOUT_INF_DVI, + VOUT_INF_HDMI, + VOUT_INF_LVDS, + VOUT_INF_MODE_MAX +}; + +enum vout_tvformat_t { + TV_PAL, + TV_NTSC, + TV_UNDEFINED, + TV_MAX +}; + +/* wmt.display.fb0 - op:[type:op1:op2:resx:resy:fps]:[...]:[...] +<op>:[<type>:<op1>:<op2>:<resx>:<resy>:<fps>]:[...]... +[H] <op>:= +<op>.Bit[3:0] : fb type (0-GE,1-alloc & fix,2-dynamic alloc,3-GE overscan) +<op>.Bit[7:4] : hwc type (0-normal,1-scale,2-overscan,3-virtual) +<op>.Bit[8] : multi display +<op>.Bit[9] : color format valid flag +<op>.Bit[23:16] : color format + +[H] <type>:= +1: SDA +[H]<op1>:= mode (0-YCbCr,1-VGA,2-YPbPr,4-SVideo,5-CVBS) +[H]<op2> +2: LCD +[H]<op1>:= lcd id (0-auto or OEM,1-Chilin,2-Innolux,3-AUO,4-Eking,5-Hannstar) +[H]<op2>:= +<op2>.Bit[7:0] : bit per pixel +<op2>.Bit[10:8] : rgb mode (0-888,1-555,2-666,3-565) +<op2>.Bit[11] : msb(0-lsb,1-msb) +<op2>.Bit[13:12] : swap (0-RGB [7-0], 1-RGB [0-7], 2-BGR [7-0], 3-BGR [0-7]) +3: DVI +[H]<op1> := +<op1>.Bit[7:0] : color format(6-ARGB) +<op1>.Bit[11:8] : dvi i2c bus id +<op1>.Bit[15:12] : dvi interrupt gpio no +[H]<op2> := +<op2>.Bit[0] : (0-12bit,1-24bit) +<op2>.Bit[1] : (1:interlace) +<op2>.Bit[2] : disable external device +<op2>.Bit[3] : disable external device interrupt +<op2>.Bit[4] : dvi i2c bus id valid +<op2>.Bit[5] : dvi interrupt gpio no valid +<op2>.Bit[10:8] : rgb mode (0-888,1-555,2-666,3-565) +<op2>.Bit[11] : (0-lsb,1-msb) +<op2>.Bit[13:12] : swap (0-RGB [7-0], 1-RGB [0-7], 2-BGR [7-0], 3-BGR [0-7]) +4: HDMI +[H]<op1> (1-422,3-444,6-ARGB) +[H]<op2> := +<op2>.Bit[0] : (0-12bit,1-24bit) +<op2>.Bit[1] : (1:interlace) +<op2>.Bit[2] : (1:CEC) +<op2>.Bit[3] : (1:disable) +<op2>.Bit[4] : (1:sp mode) +6:LVDS +same as LCD +8: virtual frame buffer +[H]<op1> (0-disable,1-enable) + +[D] <resx> := horizontal resolution +[D] <resy> := vertical resolution +[D] <fps> := frame per second +*/ + +#define WMT_DISP_FB_MULTI BIT(8) +#define WMT_DISP_FB_COLFMT BIT(9) +#define WMT_DISP_FB_COLFMT_MASK 0xFF0000 + +#define WMT_DISP_FB_GET_BPP(a) (a & 0xFF) +#define WMT_DISP_FB_GET_RGB_MODE(a) ((a & 0x700) >> 8) +#define WMT_DISP_FB_MSB BIT(11) +#define WMT_DISP_FB_RGB_SWAP(a) ((a & 0x3000) >> 12) + +#define WMT_DISP_FB_DVI_24BIT BIT(0) +#define WMT_DISP_FB_INTERLACE BIT(1) +#define WMT_DISP_FB_DISABLE_EXTDEV BIT(2) +#define WMT_DISP_FB_DISBALE_DVI_INT BIT(3) +#define WMT_DISP_FB_DVI_I2C BIT(4) +#define WMT_DISP_FB_DVI_INT BIT(5) + +#define WMT_DISP_FB_HDMI_CEC BIT(2) +#define WMT_DISP_FB_HDMI_DISABLE BIT(3) +#define WMT_DISP_FB_HDMI_SP_MODE BIT(4) + +enum vout_alloc_mode_t { + VOUT_ALLOC_GE, + VOUT_ALLOC_FIX_MB, + VOUT_ALLOC_DYNAMIC_MB, + VOUT_ALLOC_GE_OVERSCAN, + VOUT_ALLOC_MODE_MAX +}; + +enum vout_hwc_mode_t { + VOUT_HWC_NORMAL, + VOUT_HWC_SCALE, + VOUT_HWC_OVERSCAN, + VOUT_HWC_VIRTUAL, + VOUT_HWC_MODE_MAX +}; + +struct vout_info_t { + int num; + struct vout_t *vout[VPP_VOUT_NUM + 1]; + int multi; /* multi display in same time */ + + /* frame buffer alloc */ + enum vout_alloc_mode_t alloc_mode; + enum vout_hwc_mode_t hwc_mode; + void *fb_info_p; /* fb info pointer */ +#ifdef CONFIG_KERNEL + struct semaphore sem; +#endif + + int resx; + int resy; + int resx_virtual; + int resy_virtual; + int bpp; + int fps; + unsigned int pixclk; + unsigned int option; + + struct fb_videomode *fixed_vmode; + int fixed_width; + int fixed_height; + vdo_framebuf_t fb; +#ifdef CONFIG_UBOOT + struct fb_videomode *p_vmode; +#endif + struct vpp_dbg_timer_t pandisp_timer; + unsigned int mb; + unsigned int mb_size; +}; + +struct vout_audio_t { + int fmt; /* sample bits */ + int sample_rate; /* sample rate */ + int channel; /* channel count */ +}; + +struct vout_t; +struct vout_inf_t; + +#define VOUT_DEV_CAP_FIX_RES 0x1 +#define VOUT_DEV_CAP_EDID 0x2 +#define VOUT_DEV_CAP_AUDIO 0x4 +#define VOUT_DEV_CAP_FIX_PLUG 0x8 + +struct vout_dev_t { + struct vout_dev_t *next; + char name[10]; + enum vout_inf_mode_t mode; + struct vout_t *vout; + unsigned int capability; + + int (*init)(struct vout_t *vo); + void (*set_power_down)(int enable); + int (*set_mode)(unsigned int *option); + int (*config)(struct vout_info_t *info); + int (*check_plugin)(int hotplug); + int (*get_edid)(char *buf); + int (*set_audio)(struct vout_audio_t *arg); + int (*interrupt)(void); + void (*poll)(void); + int (*suspend)(void); + int (*resume)(void); +}; + +enum vout_blank_t { + VOUT_BLANK_UNBLANK, /* screen: unblanked, hsync: on, vsync: on */ + VOUT_BLANK_NORMAL, /* screen: blanked, hsync: on, vsync: on */ + VOUT_BLANK_VSYNC_SUSPEND,/* screen: blanked, hsync: on, vsync: off */ + VOUT_BLANK_HSYNC_SUSPEND,/* screen: blanked, hsync: off, vsync: on */ + VOUT_BLANK_POWERDOWN /* screen: blanked, hsync: off, vsync: off */ +}; + +#define VOUT_CAP_INTERFACE 0x000000FF +#define VOUT_CAP_BUS 0x00000F00 +#define VOUT_CAP_GOVR 0x0000F000 +#define VOUT_CAP_EXT_DEV 0x00010000 +#define VOUT_CAP_FIX_PLUG 0x00020000 +#define VOUT_CAP_AUDIO 0x00040000 +#define VOUT_CAP_EDID 0x00080000 + +struct vout_t { + int num; + unsigned int fix_cap; + struct vout_info_t *info; + struct vout_inf_t *inf; /* interface ops */ + struct vout_dev_t *dev; /* device ops */ + struct govrh_mod_t *govr; + int resx; + int resy; + int fps; + int pixclk; + unsigned int status; +#ifdef CONFIG_VOUT_EDID_ALLOC + char *edid; +#else + char edid[128*EDID_BLOCK_MAX]; +#endif + struct edid_info_t edid_info; + unsigned int option[3]; + enum vout_blank_t pre_blank; + int disable; +}; + +#define VOUT_INF_CAP_FIX_PLUG BIT(0) +struct vout_inf_t { + enum vout_inf_mode_t mode; + unsigned int capability; + + /* function */ + int (*init)(struct vout_t *vo, int arg); + int (*uninit)(struct vout_t *vo, int arg); + int (*blank)(struct vout_t *vo, enum vout_blank_t arg); + int (*config)(struct vout_t *vo, int arg); + int (*chkplug)(struct vout_t *vo, int arg); + int (*get_edid)(struct vout_t *vo, int arg); +/* int (*ioctl)(struct vout_t *vo,int arg); */ +}; + +/*-------------------- EXPORTED PRIVATE VARIABLES ---------------------------*/ +#ifdef VOUT_C /* allocate memory for variables only in vout.c */ +#define EXTERN + +const char *vout_inf_str[] = {"DVI", "HDMI", "LVDS", "VGA", "SDA", "SDD"}; +const char *vout_adpt_str[] = {"SD_DIGITAL", "SD_DIGITAL", "LCD", "DVI", + "HDMI", "DVO2HDMI", "LVDS", "VGA", "BOOT"}; + +#else +#define EXTERN extern + +extern const char *vout_inf_str[]; +extern const char *vout_adpt_str[]; + +#endif /* ifdef VOUT_C */ + +EXTERN struct vout_info_t *vout_info[VPP_VOUT_INFO_NUM]; + +/* EXTERN int vo_xxx; *//*Example*/ +EXTERN int (*vout_board_info)(int arg); + +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS -----------------------------*/ +/* #define VO_XXX_YYY xxxx *//*Example*/ +/*--------------------- EXPORTED PRIVATE FUNCTIONS -------------------------*/ +/* extern void vo_xxx(void); *//*Example*/ + +void vout_register(int no, struct vout_t *vo); +struct vout_t *vout_get_entry(int no); +struct vout_info_t *vout_get_info_entry(int no); +void vout_change_status(struct vout_t *vo, int mask, int sts); +int vout_query_inf_support(int no, enum vout_inf_mode_t mode); + +int vout_inf_register(enum vout_inf_mode_t mode, struct vout_inf_t *inf); +struct vout_inf_t *vout_inf_get_entry(enum vout_inf_mode_t mode); + +int vout_device_register(struct vout_dev_t *ops); +struct vout_dev_t *vout_get_device(struct vout_dev_t *ops); + +struct vout_t *vout_get_entry_adapter(enum vout_mode_t mode); +struct vout_inf_t *vout_get_inf_entry_adapter(enum vout_mode_t mode); +int vout_info_add_entry(int no, struct vout_t *vo); +struct vout_info_t *vout_info_get_entry(int no); +void vout_info_set_fixed_timing(int no, struct fb_videomode *vmode); +struct govrh_mod_t *vout_info_get_govr(int no); +enum vpp_vout_s vout_get_mode_adapter(struct vout_t *vout); + +int vout_config(struct vout_info_t *info, struct fb_videomode *vmode, + vdo_framebuf_t *fb); +int vout_set_mode(int no, enum vout_inf_mode_t mode); +int vout_set_blank(int no, enum vout_blank_t blank); +void vout_set_framebuffer(struct vout_info_t *info, vdo_framebuf_t *fb); +int vout_chkplug(int no); +void vout_set_int_type(int type); +char *vout_get_edid(int no); +int vout_get_edid_option(int no); +int vout_check_plugin(int clr_sts); +void vout_print_entry(struct vout_t *vo); + +int vout_init(void); +int vout_exit(void); +int vo_i2c_proc(int id, unsigned int addr, unsigned int index, + char *pdata, int len); +int vout_set_audio(struct vout_audio_t *arg); +int vout_find_edid_support_mode(struct edid_info_t *info, + unsigned int *resx, unsigned int *resy, unsigned int *fps, int r_16_9); +int vout_check_ratio_16_9(unsigned int resx, unsigned int resy); +unsigned int vout_get_mask(struct vout_info_t *vo_info); +void vout_set_int_enable(int enable); +int vout_get_clr_int(void); +void vo_hdmi_set_clock(int enable); +enum vout_tvformat_t vout_get_tvformat(void); +#ifndef CONFIG_VPOST +int vout_find_match_mode(int fbnum, + struct fb_videomode *vmode, int match); +#endif +#define VOUT_MODE_OPTION_LESS BIT0 +#define VOUT_MODE_OPTION_GREATER BIT1 +#define VOUT_MODE_OPTION_EDID BIT2 +#define VOUT_MODE_OPTION_INTERLACE BIT3 +#define VOUT_MODE_OPTION_PROGRESS BIT4 +struct fb_videomode *vout_get_video_mode(int vout_num, + struct fb_videomode *vmode, int option); +int vout_get_width_height(int fbnum, int *width, int *height); +void vo_hdmi_cp_set_enable_tmr(int sec); +struct vout_dev_t *lcd_get_dev(void); +#ifdef __cplusplus +} +#endif + +#endif /* ifndef VOUT_H */ + +/*=== END vout.h ==========================================================*/ diff --git a/common/wmt_display/vpp-osif.c b/common/wmt_display/vpp-osif.c new file mode 100755 index 0000000..f679946 --- /dev/null +++ b/common/wmt_display/vpp-osif.c @@ -0,0 +1,912 @@ +/*++ + * linux/drivers/video/wmt/osif.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define VPP_OSIF_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ +/*----------------------- DEPENDENCE -----------------------------------------*/ +#include "vpp.h" + +/*----------------------- PRIVATE MACRO --------------------------------------*/ + +/*----------------------- PRIVATE CONSTANTS ----------------------------------*/ +/* #define LVDS_XXXX 1 *//*Example*/ + +/*----------------------- PRIVATE TYPE --------------------------------------*/ +/* typedef xxxx lvds_xxx_t; *//*Example*/ + +/*----------EXPORTED PRIVATE VARIABLES are defined in lvds.h -------------*/ +/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/ +/* int lvds_xxx; *//*Example*/ +#ifdef __KERNEL__ +static DEFINE_SPINLOCK(vpp_irqlock); +static unsigned long vpp_lock_flags; +#endif + +/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/ +/* void lvds_xxx(void); *//*Example*/ + +/*----------------------- Function Body --------------------------------------*/ +#ifdef __KERNEL__ +#include <asm/io.h> +#include <linux/proc_fs.h> +#else +inline unsigned int inl(unsigned int offset) +{ + return *(unsigned int *)(offset); +} + +inline void outl(unsigned int val, unsigned int offset) +{ + (*(unsigned int *)(offset)) = val; +} + +inline unsigned short inw(unsigned int offset) +{ + return *(unsigned short *)(offset); +} + +inline void outw(unsigned short val, unsigned int offset) +{ + (*(unsigned short *)(offset)) = val; +} + +inline unsigned char inb(unsigned int offset) +{ + return *(unsigned char *)(offset); +} + +inline void outb(unsigned char val, unsigned int offset) +{ + (*(unsigned char *)(offset)) = val; +} +#ifndef CFG_LOADER +int get_key(void) +{ + int key; + + key = get_num(0, 256, "Input:", 5); + DPRINT("\n"); + return key; +} + +void udelay(int us) +{ + vpp_post_delay(us); +} + +void mdelay(int ms) +{ + udelay(ms * 1000); +} +#endif +#endif + +void vpp_udelay(unsigned int us) +{ +#if 1 + udelay(us); +#else + unsigned int cur; + unsigned int cross; + + if (us == 0) + return; + + cur = wmt_read_oscr(); + us = cur + us * 3; + cross = (us < cur) ? cur : 0; /* check overflow */ + while (1) { + if (cross) { + if (cur < cross) + cross = 0; + } else { + if (us < cur) + break; + } + cur = wmt_read_oscr(); + } +#endif +} + +/* Internal functions */ +U32 vppif_reg32_write(U32 offset, U32 mask, U32 shift, U32 val) +{ + U32 new_val; + +#if 0 + if (val > (mask >> shift)) + MSG("*E* check the parameter 0x%x 0x%x 0x%x 0x%x\n", + offset, mask, shift, val); +#endif + new_val = (inl(offset) & ~(mask)) | (((val) << (shift)) & mask); + outl(new_val, offset); + return new_val; +} +EXPORT_SYMBOL(vppif_reg32_write); + +U32 vppif_reg32_read(U32 offset, U32 mask, U32 shift) +{ + return (inl(offset) & mask) >> shift; +} +EXPORT_SYMBOL(vppif_reg32_read); + +U32 vppif_reg32_mask(U32 offset, U32 mask, U32 shift) +{ + return mask; +} + +int vpp_request_irq(unsigned int irq_no, void *routine, + unsigned int flags, char *name, void *arg) +{ +#if 0 /* disable irq */ + return 0; +#endif + +#ifdef __KERNEL__ + if (request_irq(irq_no, routine, flags, name, arg)) { + DPRINT("[VPP] *E* request irq %s fail\n", name); + return -1; + } +#endif + return 0; +} + +void vpp_free_irq(unsigned int irq_no, void *arg) +{ +#ifdef __KERNEL__ + free_irq(irq_no, arg); +#endif +} + +#ifndef __KERNEL__ +int wmt_getsyspara(char *varname, char *varval, int *varlen) +{ +#ifdef CONFIG_VPOST + struct env_para_def param; +#endif + int i = 0; + char *p; + +#ifdef CONFIG_VPOST + p = 0; + if (env_read_para(varname, ¶m) == 0) + p = param.value; +#else + p = getenv(varname); +#endif + if (!p) { + /* printf("## Warning: %s not defined\n", varname); */ + return -1; + } + while (p[i] != '\0') { + varval[i] = p[i]; + i++; + } + varval[i] = '\0'; + *varlen = i; + /* printf("getsyspara: %s,len %d\n", p, *varlen); */ +#ifdef CONFIG_VPOST + free(param.value); +#endif + return 0; +} +#endif + +int vpp_parse_param(char *buf, unsigned int *param, + int cnt, unsigned int hex_mask) +{ + char *p; + char *endp; + int i = 0; + + if (*buf == '\0') + return 0; + + for (i = 0; i < cnt; i++) + param[i] = 0; + + p = (char *)buf; + for (i = 0; i < cnt; i++) { +#ifdef CONFIG_VPOST + param[i] = strtoul(p, &endp, + (hex_mask & (0x1 << i)) ? 16 : 0); +#else + param[i] = simple_strtoul(p, &endp, + (hex_mask & (0x1 << i)) ? 16 : 0); +#endif + if (*endp == '\0') + break; + p = endp + 1; + + if (*p == '\0') + break; + } + return i + 1; +} + +unsigned int vpp_lock_cnt; +void vpp_lock_l(void) +{ +#ifdef __KERNEL__ +#if 0 + vpp_lock_cnt++; + DPRINT("vpp_lock(%d)\n", vpp_lock_cnt); +#endif + spin_lock_irqsave(&vpp_irqlock, vpp_lock_flags); +#else +#endif +} + +void vpp_unlock(void) +{ +#ifdef __KERNEL__ +#if 0 + vpp_lock_cnt--; + DPRINT("vpp_unlock(%d)\n", vpp_lock_cnt); +#endif + spin_unlock_irqrestore(&vpp_irqlock, vpp_lock_flags); +#else +#endif +} + +#ifdef __KERNEL__ +struct i2c_adapter *vpp_i2c_adapter; +struct i2c_client *vpp_i2c_client; +struct vpp_i2c_priv { + unsigned int var; +}; +static int __devinit vpp_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct vpp_i2c_priv *vpp_i2c; + int ret = 0; + + DBGMSG("\n"); + if (vpp_i2c_client == 0) + return -ENODEV; + + if (!i2c_check_functionality(vpp_i2c_client->adapter, I2C_FUNC_I2C)) { + DBG_ERR("need I2C_FUNC_I2C\n"); + return -ENODEV; + } + + vpp_i2c = kzalloc(sizeof(struct vpp_i2c_priv), GFP_KERNEL); + if (vpp_i2c == NULL) { + DBG_ERR("kzalloc fail\n"); + return -ENOMEM; + } + i2c_set_clientdata(i2c, vpp_i2c); + return ret; +} + +static int vpp_i2c_remove(struct i2c_client *client) +{ + kfree(i2c_get_clientdata(client)); + return 0; +} + +static const struct i2c_device_id vpp_i2c_id[] = { + { "vpp_i2c", 0}, + { } +}; +MODULE_DEVICE_TABLE(i2c, vpp_i2c_id); + +static struct i2c_driver vpp_i2c_driver = { + .probe = vpp_i2c_probe, + .remove = vpp_i2c_remove, + .id_table = vpp_i2c_id, + .driver = { .name = "vpp_i2c", }, +}; + +static struct i2c_board_info vpp_i2c_board_info = { + .type = "vpp_i2c", + .flags = 0x00, + .platform_data = NULL, + .archdata = NULL, + .irq = -1, +}; +#endif +#ifdef __KERNEL__ +int vpp_i2c_xfer(struct i2c_msg *msg, unsigned int num, int bus_id) +#else +int vpp_i2c_xfer(struct i2c_msg_s *msg, unsigned int num, int bus_id) +#endif +{ + int ret = 1; + +#ifdef __KERNEL__ + int i = 0; +#if 0 + if (bus_id == 1) { + ret = wmt_i2c_xfer_continue_if_4(msg, num, bus_id); + return ret; + } +#endif + + if (num > 1) { + for (i = 0; i < num - 1; ++i) + msg[i].flags |= I2C_M_NOSTART; + } + ret = i2c_transfer(vpp_i2c_adapter, msg, num); + if (ret <= 0) { + DBG_ERR("i2c fail\n"); + return ret; + } +#elif defined(CONFIG_VPOST) + ret = i2c_transfer(msg, num); +#else + ret = wmt_i2c_transfer(msg, num, bus_id); +#endif + return ret; +} + +int vpp_i2c_init(int i2c_id, unsigned short addr) +{ +#ifdef __KERNEL__ + struct i2c_board_info *vpp_i2c_bi = &vpp_i2c_board_info; + int ret = 0; + + DBGMSG("id %d,addr 0x%x\n", i2c_id, addr); + + if (i2c_id & VPP_DVI_I2C_SW_BIT) + return 0; + + i2c_id &= VPP_DVI_I2C_ID_MASK; + vpp_i2c_adapter = i2c_get_adapter(i2c_id); + if (vpp_i2c_adapter == NULL) { + DBG_ERR("can not get i2c adapter, client address error\n"); + return -ENODEV; + } + + vpp_i2c_bi->addr = addr >> 1; + + vpp_i2c_client = i2c_new_device(vpp_i2c_adapter, vpp_i2c_bi); + if (vpp_i2c_client == NULL) { + DBG_ERR("allocate i2c client failed\n"); + return -ENOMEM; + } + i2c_put_adapter(vpp_i2c_adapter); + + ret = i2c_add_driver(&vpp_i2c_driver); + if (ret) + DBG_ERR("i2c_add_driver fail\n"); + return ret; +#else + return 0; +#endif +} + +int vpp_i2c_release(void) +{ +#ifdef __KERNEL__ + if (vpp_i2c_client) { + i2c_del_driver(&vpp_i2c_driver); + i2c_unregister_device(vpp_i2c_client); + vpp_i2c_remove(vpp_i2c_client); + vpp_i2c_client = 0; + } +#else + +#endif + return 0; +} + +#ifdef __KERNEL__ +static DEFINE_SEMAPHORE(vpp_i2c_sem); +#endif +void vpp_i2c_set_lock(int lock) +{ +#ifdef __KERNEL__ + if (lock) + down(&vpp_i2c_sem); + else + up(&vpp_i2c_sem); +#endif +} + +int vpp_i2c_lock; +int vpp_i2c_enhanced_ddc_read(int id, unsigned int addr, + unsigned int index, char *pdata, int len) +{ +#ifdef __KERNEL__ + struct i2c_msg msg[3]; +#else + struct i2c_msg_s msg[3]; +#endif + unsigned char buf[len + 1]; + unsigned char buf2[2]; + int ret = 0; + + vpp_i2c_set_lock(1); + + if (vpp_i2c_lock) + DBG_ERR("in lock\n"); + + vpp_i2c_lock = 1; + + id = id & VPP_DVI_I2C_ID_MASK; + buf2[0] = 0x1; + buf2[1] = 0x0; + msg[0].addr = (0x60 >> 1); + msg[0].flags = 0 ; + msg[0].flags &= ~(I2C_M_RD); + msg[0].len = 1; + msg[0].buf = buf2; + + addr = (addr >> 1); + memset(buf, 0x55, len + 1); + buf[0] = index; + buf[1] = 0x0; + + msg[1].addr = addr; + msg[1].flags = 0 ; + msg[1].flags &= ~(I2C_M_RD); + msg[1].len = 1; + msg[1].buf = buf; + + msg[2].addr = addr; + msg[2].flags = 0 ; + msg[2].flags |= (I2C_M_RD); + msg[2].len = len; + msg[2].buf = buf; + + ret = vpp_i2c_xfer(msg, 3, id); + memcpy(pdata, buf, len); + vpp_i2c_lock = 0; + vpp_i2c_set_lock(0); + return ret; +} /* End of vpp_i2c_enhanced_ddc_read */ +EXPORT_SYMBOL(vpp_i2c_enhanced_ddc_read); + +int vpp_i2c_read(int id, unsigned int addr, + unsigned int index, char *pdata, int len) +{ + int ret = 0; + + DBG_DETAIL("(%d,0x%x,%d,%d)\n", id, addr, index, len); + vpp_i2c_set_lock(1); + if (vpp_i2c_lock) + DBG_ERR("in lock\n"); + + vpp_i2c_lock = 1; + + id = id & VPP_DVI_I2C_ID_MASK; + switch (id) { + case 0 ... 0xF: /* hw i2c */ + { +#ifdef CONFIG_KERNEL + struct i2c_msg msg[2]; +#else + struct i2c_msg_s msg[2] ; +#endif + unsigned char buf[len + 1]; + + addr = (addr >> 1); + + buf[0] = index; + buf[1] = 0x0; + + msg[0].addr = addr; /* slave address */ + msg[0].flags = 0 ; + msg[0].flags &= ~(I2C_M_RD); + msg[0].len = 1; + msg[0].buf = buf; + + msg[1].addr = addr; + msg[1].flags = I2C_M_RD; + msg[1].len = len; + msg[1].buf = buf; + ret = vpp_i2c_xfer(msg, 2, id); + memcpy(pdata, buf, len); + } + break; + default: +#ifdef CONFIG_KERNEL + ret = vo_i2c_proc((id & 0xF), (addr | BIT0), index, pdata, len); +#endif + break; + } +#ifdef DEBUG + { + int i; + + DBGMSG("vpp_i2c_read(addr 0x%x,index 0x%x,len %d\n", addr, index, len); + for (i = 0; i < len; i += 8) { + DBGMSG("%d : 0x%02x 0x%02x 0x%02x 0x%02x", + i, pdata[i], pdata[i + 1], pdata[i + 2], pdata[i + 3]); + DBGMSG(" 0x%02x 0x%02x 0x%02x 0x%02x\n", + pdata[i + 4], pdata[i + 5], pdata[i + 6], pdata[i + 7]); + } + } +#endif + vpp_i2c_lock = 0; + vpp_i2c_set_lock(0); + return ret; +} +EXPORT_SYMBOL(vpp_i2c_read); + +int vpp_i2c_write(int id, unsigned int addr, unsigned int index, + char *pdata, int len) +{ + int ret = 0; + + DBG_DETAIL("(%d,0x%x,%d,%d)\n", id, addr, index, len); + vpp_i2c_set_lock(1); + if (vpp_i2c_lock) + DBG_ERR("in lock\n"); + + vpp_i2c_lock = 1; + + id = id & VPP_DVI_I2C_ID_MASK; + switch (id) { + case 0 ... 0xF: /* hw i2c */ + { +#ifdef CONFIG_KERNEL + struct i2c_msg msg[1]; +#else + struct i2c_msg_s msg[1] ; +#endif + unsigned char buf[len + 1]; + + addr = (addr >> 1); + buf[0] = index; + memcpy(&buf[1], pdata, len); + msg[0].addr = addr; /* slave address */ + msg[0].flags = 0 ; + msg[0].flags &= ~(I2C_M_RD); + msg[0].len = len + 1; + msg[0].buf = buf; + ret = vpp_i2c_xfer(msg, 1, id); + } + break; + default: +#ifdef CONFIG_KERNEL + vo_i2c_proc((id & 0xF), (addr & ~BIT0), index, pdata, len); +#endif + break; + } + +#ifdef DEBUG + { + int i; + + DBGMSG("vpp_i2c_write(addr 0x%x,index 0x%x,len %d\n", addr, index, len); + for (i = 0; i < len; i += 8) { + DBGMSG("%d : 0x%02x 0x%02x 0x%02x 0x%02x", + i, pdata[i], pdata[i + 1], pdata[i + 2], pdata[i + 3]); + DBGMSG(" 0x%02x 0x%02x 0x%02x 0x%02x\n", + pdata[i + 4], pdata[i + 5], pdata[i + 6], pdata[i + 7]); + } + } +#endif + vpp_i2c_lock = 0; + vpp_i2c_set_lock(0); + return ret; +} +EXPORT_SYMBOL(vpp_i2c_write); + +void DelayMS(int ms) +{ + mdelay(ms); +} +EXPORT_SYMBOL(DelayMS); + +/*----------------------- VPP debug --------------------------------------*/ +#define VPP_DEBUG_FUNC +#ifdef VPP_DEBUG_FUNC +#define VPP_DBG_TMR_NUM 3 +/* #define VPP_DBG_DIAG_NUM 100 */ +#ifdef VPP_DBG_DIAG_NUM +char vpp_dbg_diag_str[VPP_DBG_DIAG_NUM][100]; +int vpp_dbg_diag_index; +int vpp_dbg_diag_delay; +#endif + +int vpp_check_dbg_level(enum vpp_dbg_level_t level) +{ + if (level == VPP_DBGLVL_ALL) + return 1; + + switch (g_vpp.dbg_msg_level) { + case VPP_DBGLVL_DISABLE: + break; + case VPP_DBGLVL_ALL: + return 1; + default: + if (g_vpp.dbg_msg_level == level) + return 1; + break; + } + return 0; +} + +void vpp_dbg_show(int level, int tmr, char *str) +{ +#ifdef __KERNEL__ + static struct timeval pre_tv[VPP_DBG_TMR_NUM]; + struct timeval tv; + unsigned int tm_usec = 0; + + if (vpp_check_dbg_level(level) == 0) + return; + + if (tmr && (tmr <= VPP_DBG_TMR_NUM)) { + do_gettimeofday(&tv); + if (pre_tv[tmr - 1].tv_sec) + tm_usec = (tv.tv_sec == pre_tv[tmr - 1].tv_sec) ? + (tv.tv_usec - pre_tv[tmr - 1].tv_usec) : + (1000000 + tv.tv_usec - pre_tv[tmr - 1].tv_usec); + pre_tv[tmr - 1] = tv; + } + +#ifdef VPP_DBG_DIAG_NUM + if (level == VPP_DBGLVL_DIAG) { + if (str) { + char *ptr = &vpp_dbg_diag_str[vpp_dbg_diag_index][0]; + sprintf(ptr, "%s (%d,%d)(T%d %d usec)", str, + (int)tv.tv_sec, (int)tv.tv_usec, tmr, + (int) tm_usec); + vpp_dbg_diag_index = (vpp_dbg_diag_index + 1) + % VPP_DBG_DIAG_NUM; + } + + if (vpp_dbg_diag_delay) { + vpp_dbg_diag_delay--; + if (vpp_dbg_diag_delay == 0) { + int i; + + DPRINT("----- VPP DIAG -----\n"); + for (i = 0; i < VPP_DBG_DIAG_NUM; i++) { + DPRINT("%02d : %s\n", i, + &vpp_dbg_diag_str[vpp_dbg_diag_index][0]); + vpp_dbg_diag_index = (vpp_dbg_diag_index + 1) + % VPP_DBG_DIAG_NUM; + } + } + } + return; + } +#endif + + if (str) { + if (tmr) + DPRINT("[VPP] %s (T%d period %d usec)\n", str, + tmr - 1, (int) tm_usec); + else + DPRINT("[VPP] %s\n", str); + } +#else + if (vpp_check_dbg_level(level) == 0) + return; + + if (str) + DPRINT("[VPP] %s\n", str); +#endif +} /* End of vpp_dbg_show */ + +void vpp_dbg_show_val1(int level, int tmr, char *str, int val) +{ + if (vpp_check_dbg_level(level)) { + char buf[50]; + + sprintf(buf, "%s 0x%x", str, val); + vpp_dbg_show(level, tmr, buf); + } +} + +#ifdef __KERNEL__ +static DECLARE_WAIT_QUEUE_HEAD(vpp_dbg_wq); +void vpp_dbg_wait(char *str) +{ + DPRINT("[VPP] vpp_dbg_wait(%s)\n", str); + wait_event_interruptible(vpp_dbg_wq, (g_vpp.dbg_wait)); + g_vpp.dbg_wait = 0; + DPRINT("[VPP] Exit vpp_dbg_wait\n"); +} + +void vpp_dbg_wake_up(void) +{ + wake_up(&vpp_dbg_wq); +} + +int vpp_dbg_get_period_usec(struct vpp_dbg_period_t *p, int cmd) +{ + struct timeval tv; + int tm_usec = 0; + + if (p == 0) + return 0; + + do_gettimeofday(&tv); + if (p->pre_tv.tv_sec) + tm_usec = (tv.tv_sec == p->pre_tv.tv_sec) ? + (tv.tv_usec - p->pre_tv.tv_usec) : + (1000000 + tv.tv_usec - p->pre_tv.tv_usec); + p->pre_tv = tv; + if (cmd == 0) { /* reset */ + p->index = 0; + memset(&p->period_us, 0, VPP_DBG_PERIOD_NUM); + } else if (p->index < VPP_DBG_PERIOD_NUM) { + p->period_us[p->index] = tm_usec; + p->index++; + } + + if (cmd == 2) { /* show */ + int i, sum = 0; + + DPRINT("[VPP] period"); + for (i = 0; i < VPP_DBG_PERIOD_NUM; i++) { + DPRINT(" %d", p->period_us[i]); + sum += p->period_us[i]; + } + DPRINT(",sum %d\n", sum); + } + return tm_usec; +} + +void vpp_dbg_timer(struct vpp_dbg_timer_t *p, char *str, int cmd) +{ + struct timeval tv; + int tm_usec = 0; + int initial = 0; + + if (p == 0) + return; + + if (p->reset == 0) { /* default */ + p->reset = 150; + initial = 1; + } + + do_gettimeofday(&tv); + if (p->pre_tv.tv_sec) + tm_usec = (tv.tv_sec == p->pre_tv.tv_sec) ? + (tv.tv_usec - p->pre_tv.tv_usec) : + (1000000 + tv.tv_usec - p->pre_tv.tv_usec); + p->pre_tv = tv; + switch (cmd) { + case 0: /* initial */ + initial = 1; + break; + case 1: /* start */ + break; + case 2: /* end */ + p->cnt++; + p->sum += tm_usec; + if (p->min > tm_usec) + p->min = tm_usec; + if (p->max < tm_usec) + p->max = tm_usec; + if (p->threshold && (tm_usec >= p->threshold)) + MSG("%s tmr %d over %d\n", str, tm_usec, p->threshold); + if (p->cnt >= p->reset) { + int us_1t; + + us_1t = p->sum / p->cnt; + MSG("%s(Cnt %d)Sum %d us,Avg %d,Min %d,Max %d,", + str, p->cnt, p->sum, us_1t, p->min, p->max); + MSG("fps %d.%02d\n", 1000000 / us_1t, + (100000000 / us_1t) % 100); + initial = 1; + } + break; + default: + break; + } + + if (initial) { + p->cnt = 0; + p->sum = 0; + p->min = ~0; + p->max = 0; + } +} +#endif +#else +void vpp_dbg_show(int level, int tmr, char *str) {} +static void vpp_dbg_show_val1(int level, int tmr, char *str, int val) {} +void vpp_dbg_wait(char *str) {} +#endif + +#if 0 +static void load_regs(struct pt_regs *ptr) +{ + asm volatile( + "stmia %0, {r0 - r15}\n\t" + : + : "r" (ptr) + : "memory" + ); +} + +void vpp_dbg_back_trace(void) +{ + struct pt_regs *ptr; + unsigned int fp; + unsigned long flags; + + ptr = kmalloc(sizeof(struct pt_regs), GFP_KERNEL); + + local_irq_save(flags); + + MSG("\n\nstart back trace...\n"); + load_regs(ptr); + fp = ptr->ARM_fp; + c_backtrace(fp, 0x1f); + MSG("back trace end...\n\n"); + + local_irq_restore(flags); + + kfree(ptr); +} +EXPORT_SYMBOL(vpp_dbg_back_trace); +#endif + +void vpp_reg_dump(unsigned int addr, int size) +{ + int i; + + for (i = 0; i < size; i += 16) { + DPRINT("0x%8x : 0x%08x 0x%08x 0x%08x 0x%08x\n", + addr + i, inl(addr + i), + inl(addr + i + 4), + inl(addr + i + 8), + inl(addr + i + 12)); + } +} + +unsigned int *vpp_backup_reg(unsigned int addr, unsigned int size) +{ + unsigned int *ptr; + int i; + + size += 4; + ptr = kmalloc(size, GFP_KERNEL); + if (ptr == 0) { + DPRINT("[VPP] *E* malloc backup fail\n"); + return 0; + } + + for (i = 0; i < size; i += 4) + ptr[i / 4] = inl(addr + i); + return ptr; +} + +int vpp_restore_reg(unsigned int addr, unsigned int size, + unsigned int *reg_ptr) +{ + int i; + + if (reg_ptr == NULL) + return 0; + + size += 4; + for (i = 0; i < size; i += 4) + outl(reg_ptr[i / 4], addr + i); + kfree(reg_ptr); + reg_ptr = 0; + return 0; +} + diff --git a/common/wmt_display/vpp-osif.h b/common/wmt_display/vpp-osif.h new file mode 100755 index 0000000..3117e31 --- /dev/null +++ b/common/wmt_display/vpp-osif.h @@ -0,0 +1,266 @@ +/*++ + * linux/drivers/video/wmt/vpp-osif.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#ifndef VPP_OSIF_H +#define VPP_OSIF_H + +/*-------------------- DEPENDENCY -------------------------------------*/ +#ifdef CFG_LOADER + #define CONFIG_UBOOT + + #ifdef __KERNEL__ + #undef __KERNEL__ + #endif +#elif defined(__KERNEL__) + #define CONFIG_KERNEL +#else + #define CONFIG_VPOST +#endif + +/* -------------------------------------------------- */ +#ifdef DEBUG + #define DBG_MSG(fmt, args...) DPRINT("{%s} " fmt, __func__, ## args) +#else + #define DBG_MSG(fmt, args...) +#endif + +#ifdef DEBUG_DETAIL +#define DBG_DETAIL(fmt, args...) DPRINT("{%s} " fmt, __func__, ## args) +#else +#define DBG_DETAIL(fmt, args...) +#endif +#define MSG(fmt, args...) DPRINT("" fmt, ## args) +#define DBG_ERR(fmt, args...) \ + DPRINT(KERN_ERR "*E* {%s} " fmt, __func__, ## args) +#define DMSG(fmt, args...) \ + DPRINT("{%s,%d} " fmt, __func__, __LINE__, ## args) + +#ifdef DEBUG +#define DBGMSG(fmt, args...) DPRINT("{%s} " fmt, __func__, ## args) +#else +#define DBGMSG(fmt, args...) +#endif + +#if 0 /* disable all msg */ +#undef MSG +#undef DBGMSG + +#define MSG(fmt, args...) +#define DBGMSG(fmt,args...) +#endif + +#define HW_REG volatile + +/* -------------------------------------------------- */ +#ifdef CONFIG_KERNEL +#include <linux/version.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/delay.h> +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/spinlock.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/i2c.h> +#include <linux/wmt-mb.h> +#include <linux/netlink.h> +#include <linux/switch.h> +#include <net/sock.h> +#include <mach/hardware.h> +#include <mach/wmt_mmap.h> + +#define SA_INTERRUPT IRQF_DISABLED +#endif + +/* -------------------------------------------------- */ +#ifdef CONFIG_UBOOT +#define CONFIG_WMT_EDID +#define CONFIG_WMT_EXT_DEV_PLUG_DISABLE + +#include <linux/types.h> +#include "../../board/wmt/include/common_def.h" +#include <common.h> +#include <malloc.h> +#include "hw_devices.h" +#include "hw/wmt_mmap.h" +#include "hw/wmt-pwm.h" +#include "hw/wmt-ost.h" +#include "hw/wmt_gpio.h" +#include "wmt_display.h" +#include "../../board/wmt/include/wmt_clk.h" +#include "../../board/wmt/include/i2c.h" + +#define abs(a) ((a>=0)? a:(-1*a)) +#endif + +/* -------------------------------------------------- */ +#ifdef CONFIG_VPOST +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "global.h" +#define __ASM_ARCH_HARDWARE_H +#include "../include/wmt_mmap.h" +#include "../pmc/wmt_clk.h" +#include "../i2c/i2c.h" +#include "linux/wmt-mb.h" +#endif + +/* following is the C++ header */ +#ifdef __cplusplus +extern "C" { +#endif + +/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/ +#ifdef CONFIG_KERNEL +#define THE_MB_USER "VPP-MB" +#define DPRINT printk +/* -------------------------------------------------- */ +#endif + +#ifdef CONFIG_UBOOT +#define IRQ_GPIO 0 + +//--> modified by howayhuo to fix the charge-animation hangup bug +#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) +//#define mdelay(x) wmt_delayus(1000*x) +//#define udelay(x) wmt_delayus(x) +//<-- end modification + +#define mb_alloc(a) malloc(a) +#define kmalloc(a,b) malloc(a) +#define kfree(a) free(a) +#define GFP_KERNEL 0 +#define module_init(a) + +#define DPRINT printf +#define mb_phys_to_virt(a) (a) +#define mb_virt_to_phys(a) (a) +#define EXPORT_SYMBOL(a) + +#define IRQF_SHARED 0 +#define IRQF_DISABLED 0 +#define SA_INTERRUPT 0 + +#define KERN_ALERT +#define KERN_ERR +#define KERN_DEBUG +#define KERN_WARNING +#define KERN_INFO + +#define printk printf +#endif + +/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/ +/* typedef void hdmi_xxx_t; *//*Example*/ + +/*-------------------- EXPORTED PRIVATE VARIABLES ----------------------------*/ +#ifdef VPP_OSIF_C +#define EXTERN +#else +#define EXTERN extern +#endif /* ifdef VPP_OSIF_C */ + +/* EXTERN int hdmi_xxx; *//*Example*/ + +#undef EXTERN + +/*--------------------- EXPORTED PRIVATE MACROS ------------------------------*/ +/* #define HDMI_XXX_YYY xxxx *//*Example*/ + +/*--------------------- EXPORTED PRIVATE FUNCTIONS --------------------------*/ +/* extern void hdmi_xxx(void); *//*Example*/ +#ifdef CONFIG_KERNEL +extern void wmt_i2c_xfer_continue_if(struct i2c_msg *msg, + unsigned int num); +extern void wmt_i2c_xfer_if(struct i2c_msg *msg); +extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg, + unsigned int num, int bus_id); +#else +inline unsigned int inl(unsigned int offset); +inline void outl(unsigned int val, unsigned int offset); +inline unsigned short inw(unsigned int offset); +inline void outw(unsigned short val, unsigned int offset); +inline unsigned char inb(unsigned int offset); +inline void outb(unsigned char val, unsigned int offset); +#endif + +#ifdef CONFIG_UBOOT +extern int wmt_getsyspara(char *varname,char *varval, int *varlen); +extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd, + int unit, int freq); +extern struct fb_var_screeninfo vfb_var; +#endif + +#ifdef CONFIG_VPOST +void vpp_initialization(int FunctionNumber); +void udelay(int us); +void mdelay(int ms); +extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd, + int unit, int freq); +extern void vpp_post_delay(U32 tmr); +extern int get_num(unsigned int min, unsigned int max, + char *message, unsigned int retry); +#endif + +extern unsigned int wmt_read_oscr(void); +int wmt_getsyspara(char *varname,char *varval, int *varlen); +int vpp_request_irq(unsigned int irq_no, void *routine, + unsigned int flags, char *name, void *arg); +void vpp_free_irq(unsigned int irq_no, void *arg); +int vpp_parse_param(char *buf, unsigned int *param, + int cnt, unsigned int hex_mask); +void vpp_lock_l(void); +void vpp_unlock(void); + +#define vpp_lock() vpp_lock_l(); \ + /* DPRINT("vpp_lock %s %d\n",__FUNCTION__,__LINE__); */ + +int vpp_i2c_write(int id, unsigned int addr, unsigned int index, + char *pdata, int len); +int vpp_i2c_read(int id, unsigned int addr, unsigned int index, + char *pdata, int len); +int vpp_i2c_enhanced_ddc_read(int id, unsigned int addr, + unsigned int index, char *pdata, int len); +int vpp_i2c_init(int i2c_id, unsigned short addr); +int vpp_i2c_release(void); +void vpp_set_clock_enable(enum dev_id dev, int enable, int force); +void vpp_udelay(unsigned int us); +unsigned int vppif_reg32_write(unsigned int offset, + unsigned int mask, unsigned int shift, unsigned int val); +unsigned int vppif_reg32_read(unsigned int offset, + unsigned int mask, unsigned int shift); +unsigned int vppif_reg32_mask(unsigned int offset, + unsigned int mask, unsigned int shift); +void vpp_reg_dump(unsigned int addr, int size); +unsigned int *vpp_backup_reg(unsigned int addr, unsigned int size); +int vpp_restore_reg(unsigned int addr, + unsigned int size, unsigned int *reg_ptr); + +#ifdef __cplusplus +} +#endif +#endif /* VPP_OSIF_H */ + diff --git a/common/wmt_display/vpp.c b/common/wmt_display/vpp.c new file mode 100755 index 0000000..544d9db --- /dev/null +++ b/common/wmt_display/vpp.c @@ -0,0 +1,1413 @@ +/*++ + * linux/drivers/video/wmt/vpp.c + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#define VPP_C +#undef DEBUG +/* #define DEBUG */ +/* #define DEBUG_DETAIL */ + +#include "vpp.h" + +struct vpp_mod_base_t *vpp_mod_base_list[VPP_MOD_MAX]; + +unsigned int vpp_get_chipid(void) +{ + /* byte 3,2: chip id, byte 1:ver id, byte 0:sub id */ + /* ex: 0x34290101 (0x3429 A0), 0x34290102 (0x3429 A1) */ + return inl(SYSTEM_CFG_CTRL_BASE_ADDR); +} + +inline void vpp_cache_sync(void) +{ + /* TODO */ +} + +void vpp_set_clock_enable(enum dev_id dev, int enable, int force) +{ +#ifdef CONFIG_VPP_DISABLE_PM + return; +#else + int cnt; + + do { + cnt = auto_pll_divisor(dev, + (enable) ? CLK_ENABLE : CLK_DISABLE, 0, 0); + if (enable) { + if (cnt) + break; + } else { + if (cnt == 0) + break; + } + } while (force); +/* MSG("%s(%d,%d,%d)\n", __FUNCTION__, dev, enable, cnt); */ +#endif +} + +/*----------------------- vpp module --------------------------------------*/ +void vpp_mod_unregister(vpp_mod_t mod) +{ + struct vpp_mod_base_t *mod_p; + + if (mod >= VPP_MOD_MAX) + return; + + mod_p = vpp_mod_base_list[mod]; + if (!mod_p) + return; + + kfree(mod_p->fb_p); + kfree(mod_p); + vpp_mod_base_list[mod] = 0; +} + +struct vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod, + int size, unsigned int flags) +{ + struct vpp_mod_base_t *mod_p; + + if (mod >= VPP_MOD_MAX) + return 0; + + if (vpp_mod_base_list[mod]) + vpp_mod_unregister(mod); + + mod_p = kmalloc(size, GFP_KERNEL); + if (!mod_p) + return 0; + + vpp_mod_base_list[mod] = mod_p; + memset(mod_p, 0, size); + mod_p->mod = mod; + + if (flags & VPP_MOD_FLAG_FRAMEBUF) { + mod_p->fb_p = kmalloc(sizeof(struct vpp_fb_base_t), GFP_KERNEL); + if (!mod_p->fb_p) + goto error; + memset(mod_p->fb_p, 0, sizeof(struct vpp_fb_base_t)); + } + DBG_DETAIL(" %d,0x%x,0x%x\n", mod, (int)mod_p, (int)mod_p->fb_p); + return mod_p; +error: + vpp_mod_unregister(mod); + DPRINT("vpp mod register NG %d\n", mod); + return 0; +} + +struct vpp_mod_base_t *vpp_mod_get_base(vpp_mod_t mod) +{ + if (mod >= VPP_MOD_MAX) + return 0; + return vpp_mod_base_list[mod]; +} + +struct vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod) +{ + struct vpp_mod_base_t *mod_p; + mod_p = vpp_mod_get_base(mod); + if (mod_p) + return mod_p->fb_p; + return 0; +} + +vdo_framebuf_t *vpp_mod_get_framebuf(vpp_mod_t mod) +{ + struct vpp_mod_base_t *mod_p; + + mod_p = vpp_mod_get_base(mod); + if (mod_p && mod_p->fb_p) + return &mod_p->fb_p->fb; + return 0; +} + +void vpp_mod_set_clock(vpp_mod_t mod, vpp_flag_t enable, int force) +{ + struct vpp_mod_base_t *base; + enum dev_id pll_dev; + int cur_sts; + int ret; + +#ifdef CONFIG_VPP_DISABLE_PM + return; +#endif + + base = vpp_mod_get_base(mod); + if (base == 0) + return; + + pll_dev = (base->pm & 0xFF); + if (pll_dev == 0) + return; + + enable = (enable) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE; + if (force) { + ret = auto_pll_divisor(pll_dev, + (enable) ? CLK_ENABLE : CLK_DISABLE, 0, 0); + DBG_DETAIL("[VPP] clk force(%s,%d),ret %d\n", + vpp_mod_str[mod], enable, ret); + return; + } + + cur_sts = (base->pm & VPP_MOD_CLK_ON) ? 1 : 0; + if (cur_sts != enable) { + ret = auto_pll_divisor(pll_dev, + (enable) ? CLK_ENABLE : CLK_DISABLE, 0, 0); + base->pm = (enable) ? (base->pm | VPP_MOD_CLK_ON) + : (base->pm & ~VPP_MOD_CLK_ON); + DBG_MSG("[VPP] clk enable(%s,%d,cur %d),ret %d\n", + vpp_mod_str[mod], enable, cur_sts, ret); + } +} + +vpp_display_format_t vpp_get_fb_field(vdo_framebuf_t *fb) +{ + if (fb->flag & VDO_FLAG_INTERLACE) + return VPP_DISP_FMT_FIELD; + return VPP_DISP_FMT_FRAME; +} + +unsigned int vpp_get_base_clock(vpp_mod_t mod) +{ + unsigned int clock = 0; + + switch (mod) { + default: + clock = auto_pll_divisor(DEV_VPP, GET_FREQ, 0, 0); + break; + case VPP_MOD_GOVRH: + clock = (p_govrh->vo_clock == 0) ? + auto_pll_divisor(DEV_HDMILVDS, GET_FREQ, 0, 0) : + p_govrh->vo_clock; + break; + case VPP_MOD_GOVRH2: + clock = (p_govrh2->vo_clock == 0) ? + auto_pll_divisor(DEV_DVO, GET_FREQ, 0, 0) : + p_govrh2->vo_clock; + break; + } + DBG_DETAIL("%d %d\n", mod, clock); + return clock; +} + +void vpp_show_timing(char *str, struct fb_videomode *vmode, + vpp_clock_t *clk) +{ + DPRINT("----- %s timing -----\n", str); + if (vmode) { + int pixclk; + + pixclk = (vmode->pixclock) ? PICOS2KHZ(vmode->pixclock) : 0; + pixclk *= 1000; + + DPRINT("res(%d,%d),fps %d\n", + vmode->xres, vmode->yres, vmode->refresh); + DPRINT("pixclk %d(%d),hsync %d,vsync %d\n", vmode->pixclock, + pixclk, vmode->hsync_len, vmode->vsync_len); + DPRINT("left %d,right %d,upper %d,lower %d\n", + vmode->left_margin, vmode->right_margin, + vmode->upper_margin, vmode->lower_margin); + DPRINT("vmode 0x%x,sync 0x%x\n", vmode->vmode, vmode->sync); + } + + if (clk) { + DPRINT("H beg %d,end %d,total %d\n", clk->begin_pixel_of_active, + clk->end_pixel_of_active, clk->total_pixel_of_line); + DPRINT("V beg %d,end %d,total %d\n", clk->begin_line_of_active, + clk->end_line_of_active, clk->total_line_of_frame); + DPRINT("Hsync %d, Vsync %d\n", clk->hsync, clk->vsync); + DPRINT("VBIE %d,PVBI %d\n", clk->line_number_between_VBIS_VBIE, + clk->line_number_between_PVBI_VBIS); + } + DPRINT("-----------------------\n"); +} + +void vpp_show_framebuf(char *str, vdo_framebuf_t *fb) +{ + if (fb == 0) + return; + DPRINT("----- %s framebuf -----\n", str); + DPRINT("Y addr 0x%x, size %d\n", fb->y_addr, fb->y_size); + DPRINT("C addr 0x%x, size %d\n", fb->c_addr, fb->c_size); + DPRINT("W %d, H %d, FB W %d, H %d\n", fb->img_w, fb->img_h, + fb->fb_w, fb->fb_h); + DPRINT("bpp %d, color fmt %s\n", fb->bpp, vpp_colfmt_str[fb->col_fmt]); + DPRINT("H crop %d, V crop %d, flag 0x%x\n", + fb->h_crop, fb->v_crop, fb->flag); + DPRINT("-----------------------\n"); +} + +void vpp_show_videomode(char *str, struct fb_videomode *v) +{ + if (v == 0) + return; + DPRINT("----- %s videomode -----\n", str); + DPRINT("%dx%d@%d,%d\n", v->xres, v->yres, v->refresh, v->pixclock); + DPRINT("h sync %d,bp %d,fp %d\n", v->hsync_len, + v->left_margin, v->right_margin); + DPRINT("v sync %d,bp %d,fp %d\n", v->vsync_len, + v->upper_margin, v->lower_margin); + DPRINT("sync 0x%x,vmode 0x%x,flag 0x%x\n", v->sync, v->vmode, v->flag); + DPRINT("hsync %s,vsync %s\n", + (v->sync & FB_SYNC_HOR_HIGH_ACT) ? "hi" : "lo", + (v->sync & FB_SYNC_VERT_HIGH_ACT) ? "hi" : "lo"); + DPRINT("interlace %d,double %d\n", + (v->vmode & FB_VMODE_INTERLACED) ? 1 : 0, + (v->vmode & FB_VMODE_DOUBLE) ? 1 : 0); + DPRINT("-----------------------\n"); +} + +vpp_csc_t vpp_check_csc_mode(vpp_csc_t mode, vdo_color_fmt src_fmt, + vdo_color_fmt dst_fmt, unsigned int flags) +{ + if (mode >= VPP_CSC_MAX) + return VPP_CSC_BYPASS; + + mode = (mode >= VPP_CSC_RGB2YUV_MIN) ? + (mode - VPP_CSC_RGB2YUV_MIN) : mode; + if (src_fmt >= VDO_COL_FMT_ARGB) { + mode = VPP_CSC_RGB2YUV_MIN + mode; + src_fmt = VDO_COL_FMT_ARGB; + } else { + src_fmt = VDO_COL_FMT_YUV444; + } + dst_fmt = (dst_fmt >= VDO_COL_FMT_ARGB) ? + VDO_COL_FMT_ARGB : VDO_COL_FMT_YUV444; + if (flags == 0) + mode = (src_fmt != dst_fmt) ? mode : VPP_CSC_BYPASS; + return mode; +} + +int vpp_get_gcd(int A, int B) +{ + while (A != B) { + if (A > B) + A = A - B; + else + B = B - A; + } + return A; +} + +int vpp_set_recursive_scale(vdo_framebuf_t *src_fb, + vdo_framebuf_t *dst_fb) +{ +#ifdef WMT_FTBLK_SCL + int ret; + + ret = p_scl->scale(src_fb, dst_fb); + return ret; +#else + DBG_ERR("No scale\n"); + return 0; +#endif +} + +unsigned int vpp_convert_colfmt(int yuv2rgb, unsigned int data) +{ + unsigned int r, g, b; + unsigned int y, u, v; + unsigned int alpha; + + alpha = data & 0xff000000; + if (yuv2rgb) { + y = (data & 0xff0000) >> 16; + u = (data & 0xff00) >> 8; + v = (data & 0xff) >> 0; + + r = ((1000 * y) + 1402 * (v - 128)) / 1000; + if (r > 0xFF) + r = 0xFF; + g = ((100000 * y) - (71414 * (v - 128)) + - (34414 * (u - 128))) / 100000; + if (g > 0xFF) + g = 0xFF; + b = ((1000 * y) + (1772 * (u - 128))) / 1000; + if (b > 0xFF) + b = 0xFF; + + data = ((r << 16) + (g << 8) + b); + } else { + r = (data & 0xff0000) >> 16; + g = (data & 0xff00) >> 8; + b = (data & 0xff) >> 0; + + y = ((2990 * r) + (5870 * g) + (1440 * b)) / 10000; + if (y > 0xFF) + y = 0xFF; + u = (1280000 - (1687 * r) - (3313 * g) + (5000 * b)) / 10000; + if (u > 0xFF) + u = 0xFF; + v = (1280000 + (5000 * r) - (4187 * g) - (813 * b)) / 10000; + if (v > 0xFF) + v = 0xFF; + + data = ((y << 16) + (v << 8) + u); + } + data = data + alpha; + return data; +} + +void vpp_get_sys_parameter(void) +{ +#ifndef CONFIG_VPOST + char buf[40]; + int varlen = 40; +#else + struct env_para_def param; +#endif + + /* vpp attribute by default */ + g_vpp.dbg_msg_level = 0; + g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_SPDIF; + g_vpp.hdmi_cp_enable = 1; + +#ifdef CONFIG_KERNEL + if (govrh_get_MIF_enable(p_govrh)) + g_vpp.govrh_preinit = 1; + if (govrh_get_MIF_enable(p_govrh2)) + g_vpp.govrh_preinit = 1; + MSG("[VPP] govrh preinit %d\n", g_vpp.govrh_preinit); +#else + g_vpp.govrh_preinit = 0; + p_scl->scale_sync = 1; +#endif + +#ifndef CONFIG_VPOST + if (wmt_getsyspara("wmt.display.hdmi_audio_inf", buf, &varlen) == 0) { + if (memcmp(buf, "i2s", 3) == 0) + g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_I2S; + else if (memcmp(buf, "spdif", 5) == 0) + g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_SPDIF; + } + + g_vpp.mb_colfmt = VPP_UBOOT_COLFMT; + /* [uboot parameter] fb param : no:xresx:yres:xoffset:yoffset */ + if (wmt_getsyspara("wmt.gralloc.param", buf, &varlen) == 0) { + unsigned int parm[1]; + + vpp_parse_param(buf, (unsigned int *)parm, 1, 0x1); + if (parm[0] == 32) + g_vpp.mb_colfmt = VDO_COL_FMT_ARGB; + MSG("mb colfmt : %s,%s\n", buf, + vpp_colfmt_str[g_vpp.mb_colfmt]); + } + p_govrh->fb_p->fb.col_fmt = g_vpp.mb_colfmt; + p_govrh2->fb_p->fb.col_fmt = g_vpp.mb_colfmt; + + if (wmt_getsyspara("wmt.display.hdmi", buf, &varlen) == 0) { + unsigned int parm[1]; + + MSG("hdmi sp mode : %s\n", buf); + vpp_parse_param(buf, (unsigned int *)parm, 1, 0); + g_vpp.hdmi_sp_mode = (parm[0]) ? 1 : 0; + } + + if (wmt_getsyspara("wmt.hdmi.disable", buf, &varlen) == 0) + g_vpp.hdmi_disable = 1; + + /* [uboot parameter] reg operation : addr op val */ + if (wmt_getsyspara("wmt.display.regop", buf, &varlen) == 0) { + unsigned int addr; + unsigned int val; + char op; + char *p, *endp; + + p = buf; + while (1) { + addr = simple_strtoul(p, &endp, 16); + if (*endp == '\0') + break; + + op = *endp; + if (endp[1] == '~') { + val = simple_strtoul(endp + 2, &endp, 16); + val = ~val; + } else + val = simple_strtoul(endp + 1, &endp, 16); + + DBG_DETAIL(" reg op: 0x%X %c 0x%X\n", addr, op, val); + switch (op) { + case '|': + outl(inl(addr) | val, addr); + break; + case '=': + outl(val, addr); + break; + case '&': + outl(inl(addr) & val, addr); + break; + default: + DBG_ERR("Error, Unknown operator %c\n", op); + } + + if (*endp == '\0') + break; + p = endp + 1; + } + } +#else + if (env_read_para("wmt.display.hdmi", ¶m) == 0) { + g_vpp.hdmi_sp_mode = strtoul(param.value, 0, 16); + free(param.value); + } +#endif +} /* End of vpp_get_sys_parameter */ + +void vpp_init(void) +{ + struct vpp_mod_base_t *mod_p; + unsigned int mod_mask; + int i; + + auto_pll_divisor(DEV_NA12, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_VPP, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_HDCE, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_HDMII2C, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_HDMI, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_GOVRHD, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_DVO, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_LVDS, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_HDMILVDS, CLK_ENABLE, 0, 0); + auto_pll_divisor(DEV_SCL444U, CLK_ENABLE, 0, 0); + + vpp_get_sys_parameter(); + + /* init video out module first */ + if (g_vpp.govrh_preinit == 0) { + mod_mask = BIT(VPP_MOD_GOVRH2) | BIT(VPP_MOD_GOVRH) + | BIT(VPP_MOD_DISP) | BIT(VPP_MOD_LCDC); + for (i = 0; i < VPP_MOD_MAX; i++) { + if (!(mod_mask & (0x01 << i))) + continue; + mod_p = vpp_mod_get_base(i); + if (mod_p && mod_p->init) + mod_p->init(mod_p); + } + } + +#ifdef CONFIG_UBOOT + mod_mask = BIT(VPP_MOD_SCL) | BIT(VPP_MOD_SCLW); +#else + /* init other module */ + mod_mask = BIT(VPP_MOD_GOVW) | BIT(VPP_MOD_GOVM) | BIT(VPP_MOD_SCL) + | BIT(VPP_MOD_SCLW) | BIT(VPP_MOD_VPU) | BIT(VPP_MOD_VPUW) + | BIT(VPP_MOD_PIP) | BIT(VPP_MOD_VPPM); +#endif + for (i = 0; i < VPP_MOD_MAX; i++) { + if (!(mod_mask & (0x01 << i))) + continue; + mod_p = vpp_mod_get_base(i); + if (mod_p && mod_p->init) + mod_p->init(mod_p); + } + +#ifdef WMT_FTBLK_LVDS + if (!g_vpp.govrh_preinit) + lvds_init(); +#endif +#ifdef WMT_FTBLK_VOUT_HDMI + hdmi_init(); +#endif + +#ifndef CONFIG_VPOST + /* init vout device & get default resolution */ + vout_init(); +#endif + vpp_set_clock_enable(DEV_SCL444U, 0, 1); + vpp_set_clock_enable(DEV_HDMII2C, 0, 0); + vpp_set_clock_enable(DEV_HDMI, 0, 0); + vpp_set_clock_enable(DEV_HDCE, 0, 0); + vpp_set_clock_enable(DEV_LVDS, 0, 0); +} + +void vpp_get_colfmt_bpp(vdo_color_fmt colfmt, int *y_bpp, int *c_bpp) +{ + switch (colfmt) { + case VDO_COL_FMT_YUV420: + *y_bpp = 8; + *c_bpp = 4; + break; + case VDO_COL_FMT_YUV422H: + case VDO_COL_FMT_YUV422V: + *y_bpp = 8; + *c_bpp = 8; + break; + case VDO_COL_FMT_RGB_565: + case VDO_COL_FMT_RGB_1555: + case VDO_COL_FMT_RGB_5551: + *y_bpp = 16; + *c_bpp = 0; + break; + case VDO_COL_FMT_YUV444: + *y_bpp = 8; + *c_bpp = 16; + break; + case VDO_COL_FMT_RGB_888: + case VDO_COL_FMT_RGB_666: + *y_bpp = 24; + *c_bpp = 0; + break; + case VDO_COL_FMT_ARGB: + *y_bpp = 32; + *c_bpp = 0; + break; + default: + break; + } +} + +int vpp_calc_refresh(int pixclk, int xres, int yres) +{ + int refresh = 60; + int temp; + + temp = xres * yres; + if (temp) { + refresh = pixclk / temp; + if (pixclk % temp) + refresh += 1; + } + return refresh; +} + +int vpp_calc_align(int value, int align) +{ + if (value % align) { + value &= ~(align - 1); + value += align; + } + return value; +} + +int vpp_calc_fb_width(vdo_color_fmt colfmt, int width) +{ + int y_bpp, c_bpp; + + vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp); + return vpp_calc_align(width, VPP_FB_WIDTH_ALIGN / (y_bpp / 8)); +} + +void vpp_set_NA12_hiprio(int type) +{ +#if 0 + static int reg1, reg2; + + switch (type) { + case 0: /* restore NA12 priority */ + outl(reg1, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8); + outl(reg2, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC); + break; + case 1: /* set NA12 to high priority */ + reg1 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8); + reg2 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC); + outl(0x600000, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8); + outl(0x0ff00000, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC); + break; + case 2: + reg1 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8); + reg2 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC); + outl(0x20003f, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8); + outl(0x00ffff00, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC); + break; + default: + break; + } +#endif +} + +#ifdef __KERNEL__ +int vpp_set_audio(int format, int sample_rate, int channel) +{ + struct vout_audio_t info; + + MSG("set audio(fmt %d,rate %d,ch %d)\n", + format, sample_rate, channel); + info.fmt = format; + info.sample_rate = sample_rate; + info.channel = channel; + return vout_set_audio(&info); +} +#endif + +/*----------------------- vpp mb for stream ---------------------------------*/ +#ifdef CONFIG_VPP_STREAM_CAPTURE +#ifdef CONFIG_VPP_STREAM_BLOCK +DECLARE_WAIT_QUEUE_HEAD(vpp_mb_event); +#endif + +unsigned int vpp_mb_get_mask(unsigned int phy) +{ + int i; + unsigned int mask; + + for (i = 0; i < g_vpp.stream_mb_cnt; i++) { + if (g_vpp.stream_mb[i] == phy) + break; + } + if (i >= g_vpp.stream_mb_cnt) + return 0; + mask = 0x1 << i; + return mask; +} + +int vpp_mb_get(unsigned int phy) +{ + unsigned int mask; + int i, cnt; + +#ifdef CONFIG_VPP_STREAM_BLOCK + vpp_unlock(); + if (g_vpp.stream_mb_sync_flag) + vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "mb_get wait"); + + i = wait_event_interruptible_timeout(vpp_mb_event, + (g_vpp.stream_mb_sync_flag != 1), HZ / 20); + vpp_lock(); +#else /* non-block */ + if (g_vpp.stream_mb_sync_flag) { /* not new mb updated */ + vpp_dbg_show(VPP_DBGLVL_STREAM, 0, + "*W* mb_get addr not update"); + return -1; + } +#endif + g_vpp.stream_mb_sync_flag = 1; + for (i = 0, cnt = 0; i < g_vpp.stream_mb_cnt; i++) { + if (g_vpp.stream_mb_lock & (0x1 << i)) + cnt++; + } + +#if 0 + if (cnt >= (g_vpp.stream_mb_cnt - 2)) { + vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "*W* mb_get addr not free"); + return -1; + } +#endif + + mask = vpp_mb_get_mask(phy); + if (mask == 0) { + vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "*W* mb_get invalid addr"); + return -1; + } + if (g_vpp.stream_mb_lock & mask) { + vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "*W* mb_get lock addr"); + return -1; + } + g_vpp.stream_mb_lock |= mask; + if (vpp_check_dbg_level(VPP_DBGLVL_STREAM)) { + char buf[50]; + + sprintf(buf, "stream mb get 0x%x,mask 0x%x(0x%x)", + phy, mask, g_vpp.stream_mb_lock); + vpp_dbg_show(VPP_DBGLVL_STREAM, 1, buf); + } + return 0; +} + +int vpp_mb_put(unsigned int phy) +{ + unsigned int mask; + + if (phy == 0) { + g_vpp.stream_mb_lock = 0; + g_vpp.stream_mb_index = 0; + return 0; + } + + mask = vpp_mb_get_mask(phy); + if (mask == 0) { + DPRINT("[VPP] *W* mb_put addr 0x%x\n", phy); + return 1; + } + if (!(g_vpp.stream_mb_lock & mask)) + DPRINT("[VPP] *W* mb_put nonlock addr 0x%x\n", phy); + g_vpp.stream_mb_lock &= ~mask; + if (vpp_check_dbg_level(VPP_DBGLVL_STREAM)) { + char buf[50]; + + sprintf(buf, "stream mb put 0x%x,mask 0x%x(0x%x)", + phy, mask, g_vpp.stream_mb_lock); + vpp_dbg_show(VPP_DBGLVL_STREAM, 2, buf); + } + return 0; +} + +int vpp_mb_irqproc_sync(int arg) +{ + if (!g_vpp.stream_enable) + return 0; + + g_vpp.stream_sync_cnt++; + if ((g_vpp.stream_sync_cnt % 2) == 0) { + g_vpp.stream_mb_sync_flag = 0; +#ifdef CONFIG_VPP_STREAM_BLOCK + wake_up_interruptible(&vpp_mb_event); +#endif + } + return 0; +} + +/*----------------------- irq proc --------------------------------------*/ +struct vpp_irqproc_t *vpp_irqproc_array[32]; +struct list_head vpp_irqproc_free_list; +struct vpp_proc_t vpp_proc_array[VPP_PROC_NUM]; +static void vpp_irqproc_do_tasklet(unsigned long data); + +void vpp_irqproc_init(void) +{ + int i; + + INIT_LIST_HEAD(&vpp_irqproc_free_list); + + for (i = 0; i < VPP_PROC_NUM; i++) + list_add_tail(&vpp_proc_array[i].list, &vpp_irqproc_free_list); +} + +struct vpp_irqproc_t *vpp_irqproc_get_entry(enum vpp_int_t vpp_int) +{ + int no; + + if (vpp_int == 0) + return 0; + + for (no = 0; no < 32; no++) { + if (vpp_int & (0x1 << no)) + break; + } + + if (vpp_irqproc_array[no] == 0) { /* will create in first use */ + struct vpp_irqproc_t *irqproc; + + irqproc = kmalloc(sizeof(struct vpp_irqproc_t), GFP_KERNEL); + vpp_irqproc_array[no] = irqproc; + INIT_LIST_HEAD(&irqproc->list); + tasklet_init(&irqproc->tasklet, + vpp_irqproc_do_tasklet, vpp_int); + irqproc->ref = 0; + } + return vpp_irqproc_array[no]; +} /* End of vpp_irqproc_get_entry */ + +void vpp_irqproc_set_ref(struct vpp_irqproc_t *irqproc, + enum vpp_int_t type, int enable) +{ + if (enable) { + irqproc->ref++; + if (vppm_get_int_enable(type) == 0) + vppm_set_int_enable(1, type); + } else { + irqproc->ref--; + if (irqproc->ref == 0) + vppm_set_int_enable(0, type); + } +} + +static void vpp_irqproc_do_tasklet +( + unsigned long data /*!<; // tasklet input data */ +) +{ + struct vpp_irqproc_t *irqproc; + + vpp_lock(); + irqproc = vpp_irqproc_get_entry(data); + if (irqproc) { + struct list_head *cur; + struct list_head *next; + struct vpp_proc_t *entry; + + next = (&irqproc->list)->next; + while (next != &irqproc->list) { + cur = next; + next = cur->next; + entry = list_entry(cur, struct vpp_proc_t, list); + if (entry->func) { + if (entry->func(entry->arg)) + continue; + } + + if (entry->work_cnt == 0) + continue; + + entry->work_cnt--; + if (entry->work_cnt == 0) { + if (entry->wait_ms == 0) + vpp_irqproc_set_ref(irqproc, data, 0); + else + up(&entry->sem); + list_del_init(cur); + list_add_tail(&entry->list, + &vpp_irqproc_free_list); + } + } + } + vpp_unlock(); +} /* End of vpp_irqproc_do_tasklet */ + +int vpp_irqproc_work( + enum vpp_int_t type, /* interrupt type */ + int (*func)(void *argc), /* proc function pointer */ + void *arg, /* proc argument */ + int wait_ms, /* wait complete timeout (ms) */ + int work_cnt /* 0 - forever */ +) +{ + int ret; + struct vpp_proc_t *entry; + struct list_head *ptr; + struct vpp_irqproc_t *irqproc; + +#if 0 + DPRINT("[VPP] vpp_irqproc_work(type 0x%x,wait %d,cnt %d)\n", + type, wait_ms, work_cnt); +#endif + if ((vpp_irqproc_free_list.next == 0) || + list_empty(&vpp_irqproc_free_list)) { + if (func) + func(arg); + return 0; + } + + ret = 0; + vpp_lock(); + + ptr = vpp_irqproc_free_list.next; + entry = list_entry(ptr, struct vpp_proc_t, list); + list_del_init(ptr); + entry->func = func; + entry->arg = arg; + entry->type = type; + entry->wait_ms = wait_ms; + entry->work_cnt = work_cnt; + sema_init(&entry->sem, 1); + down(&entry->sem); + + irqproc = vpp_irqproc_get_entry(type); + if (irqproc) { + list_add_tail(&entry->list, &irqproc->list); + } else { + irqproc = vpp_irqproc_array[31]; + list_add_tail(&entry->list, &irqproc->list); + } + vpp_irqproc_set_ref(irqproc, type, 1); + vpp_unlock(); + + if (wait_ms) { + unsigned int tmr_cnt; + + tmr_cnt = (wait_ms * HZ) / 1000; + ret = down_timeout(&entry->sem, tmr_cnt); + if (ret) { + DPRINT("*W* vpp_irqproc_work timeout(type 0x%x,%d)\n", + type, wait_ms); + vpp_lock(); + list_del_init(ptr); + list_add_tail(ptr, &vpp_irqproc_free_list); + vpp_unlock(); + if (func) + func(arg); + } + } + + if ((work_cnt == 0) || (wait_ms == 0)) { + /* don't clear ref, forever will do in delete, + no wait will do in proc complete */ + } else { + vpp_lock(); + vpp_irqproc_set_ref(irqproc, type, 0); + vpp_unlock(); + } + return ret; +} /* End of vpp_irqproc_work */ + +void vpp_irqproc_del_work( + enum vpp_int_t type, /* interrupt type */ + int (*func)(void *argc) /* proc function pointer */ +) +{ + struct vpp_irqproc_t *irqproc; + + vpp_lock(); + irqproc = vpp_irqproc_get_entry(type); + if (irqproc) { + struct list_head *cur; + struct list_head *next; + struct vpp_proc_t *entry; + + next = (&irqproc->list)->next; + while (next != &irqproc->list) { + cur = next; + next = cur->next; + entry = list_entry(cur, struct vpp_proc_t, list); + if (entry->func == func) { + vpp_irqproc_set_ref(irqproc, type, 0); + list_del_init(cur); + list_add_tail(&entry->list, + &vpp_irqproc_free_list); + } + } + } + vpp_unlock(); +} + +/*----------------------- Linux Netlink --------------------------------------*/ +#ifdef CONFIG_VPP_NOTIFY +#define VPP_NETLINK_PROC_MAX 2 + +struct vpp_netlink_proc_t { + __u32 pid; + rwlock_t lock; +}; + +struct switch_dev vpp_sdev = { + .name = "hdmi", +}; + +static struct switch_dev vpp_sdev_hdcp = { + .name = "hdcp", +}; + +static struct switch_dev vpp_sdev_audio = { + .name = "hdmi_audio", +}; + +struct vpp_netlink_proc_t vpp_netlink_proc[VPP_NETLINK_PROC_MAX]; +static struct sock *vpp_nlfd; +static DEFINE_SEMAPHORE(vpp_netlink_receive_sem); + +struct vpp_netlink_proc_t *vpp_netlink_get_proc(int no) +{ + if (no == 0) + return 0; + if (no > VPP_NETLINK_PROC_MAX) + return 0; + return &vpp_netlink_proc[no - 1]; +} + +static void vpp_netlink_receive(struct sk_buff *skb) +{ + struct nlmsghdr *nlh = NULL; + struct vpp_netlink_proc_t *proc; + + if (down_trylock(&vpp_netlink_receive_sem)) + return; + + if (skb->len >= sizeof(struct nlmsghdr)) { + nlh = nlmsg_hdr(skb); + if ((nlh->nlmsg_len >= sizeof(struct nlmsghdr)) + && (skb->len >= nlh->nlmsg_len)) { + proc = vpp_netlink_get_proc(nlh->nlmsg_type); + if (proc) { + write_lock_bh(&proc->lock); + proc->pid = nlh->nlmsg_pid; + write_unlock_bh(&proc->lock); + DPRINT("[VPP] rx user pid 0x%x\n", proc->pid); + } + } + } + up(&vpp_netlink_receive_sem); + wmt_enable_mmfreq(WMT_MMFREQ_HDMI_PLUG, hdmi_get_plugin()); +} + +void vpp_netlink_init(void) +{ + vpp_netlink_proc[0].pid = 0; + vpp_netlink_proc[1].pid = 0; + rwlock_init(&(vpp_netlink_proc[0].lock)); + rwlock_init(&(vpp_netlink_proc[1].lock)); + vpp_nlfd = netlink_kernel_create(&init_net, NETLINK_CEC_TEST, 0, + vpp_netlink_receive, NULL, THIS_MODULE); + if (!vpp_nlfd) + DPRINT(KERN_ERR "can not create a netlink socket\n"); +} + +static ssize_t attr_show_parsed_edid(struct device *dev, + struct device_attribute *attr, char *buf) +{ + ssize_t len = 0; + int i, j; + unsigned char audio_format, sample_freq, bitrate; + int sample_freq_num, bitrate_num; + +#ifdef DEBUG + DPRINT("------- EDID Parsed ------\n"); + if(strlen(edid_parsed.tv_name.vendor_name) != 0) + DPRINT("Vendor Name: %s\n", edid_parsed.tv_name.vendor_name); + + if(strlen(edid_parsed.tv_name.monitor_name) != 0) + DPRINT("Monitor Name: %s\n", edid_parsed.tv_name.monitor_name); + + for (i = 0; i < AUD_SAD_NUM; i++) { + if (edid_parsed.sad[i].flag == 0) { + if (i == 0) + DPRINT("No SAD Data\n"); + break; + } + DPRINT("SAD %d: 0x%02X 0x%02X 0x%02X\n", i, + edid_parsed.sad[i].sad_byte[0], + edid_parsed.sad[i].sad_byte[1], + edid_parsed.sad[i].sad_byte[2]); + } + DPRINT("--------------------------\n"); +#endif + /* print Vendor Name */ + if (strlen(edid_parsed.tv_name.vendor_name) != 0) { + len += sprintf(buf + len, "%-16s", "Vendor Name"); + len += sprintf(buf + len, ": %s\n", edid_parsed.tv_name.vendor_name); + } + + /* print Monitor Name */ + if (strlen(edid_parsed.tv_name.monitor_name) != 0) { + len += sprintf(buf + len, "%-16s", "Monitor Name"); + len += sprintf(buf + len, ": %s\n", edid_parsed.tv_name.monitor_name); + } + + for (i = 0; i < AUD_SAD_NUM; i++) { + if (edid_parsed.sad[i].flag == 0) + break; + /* + SAD Byte 1 (format and number of channels): + bit 7: Reserved (0) + bit 6..3: Audio format code + 1 = Linear Pulse Code Modulation (LPCM) + 2 = AC-3 + 3 = MPEG1 (Layers 1 and 2) + 4 = MP3 + 5 = MPEG2 + 6 = AAC + 7 = DTS + 8 = ATRAC + 0, 15: Reserved + 9 = One-bit audio aka SACD + 10 = DD+ + 11 = DTS-HD + 12 = MLP/Dolby TrueHD + 13 = DST Audio + 14 = Microsoft WMA Pro + bit 2..0: number of channels minus 1 + (i.e. 000 = 1 channel; 001 = 2 channels; 111 = + 8 channels) + */ + audio_format = (edid_parsed.sad[i].sad_byte[0] & 0x78) >> 3; + if (audio_format == 0 || audio_format == 15) + continue; + + /* print header */ + len += sprintf(buf + len, "%-16s", "Audio Format"); + len += sprintf(buf + len, ": "); + + switch (audio_format) { + case 1: + len += sprintf(buf + len, "pcm"); + break; + case 2: + len += sprintf(buf + len, "ac3"); + break; + case 3: + len += sprintf(buf + len, "mpeg1"); + break; + case 4: + len += sprintf(buf + len, "mp3"); + break; + case 5: + len += sprintf(buf + len, "mpeg2"); + break; + case 6: + len += sprintf(buf + len, "aac"); + break; + case 7: + len += sprintf(buf + len, "dts"); + break; + case 8: + len += sprintf(buf + len, "atrac"); + break; + case 9: + len += sprintf(buf + len, "one_bit_audio"); + break; + case 10: + len += sprintf(buf + len, "eac3"); + break; + case 11: + len += sprintf(buf + len, "dts-hd"); + break; + case 12: + len += sprintf(buf + len, "mlp"); + break; + case 13: + len += sprintf(buf + len, "dst"); + break; + case 14: + len += sprintf(buf + len, "wmapro"); + break; + default: + break; + } + + /* separator */ + len += sprintf(buf + len, ","); + + /* number of channels */ + len += sprintf(buf + len, "%d", + (edid_parsed.sad[i].sad_byte[0] & 0x7) + 1); + + /* separator */ + len += sprintf(buf + len, ","); + + /* + SAD Byte 2 (sampling frequencies supported): + bit 7: Reserved (0) + bit 6: 192kHz + bit 5: 176kHz + bit 4: 96kHz + bit 3: 88kHz + bit 2: 48kHz + bit 1: 44kHz + bit 0: 32kHz + */ + sample_freq = edid_parsed.sad[i].sad_byte[1]; + sample_freq_num = 0; + for (j = 0; j < 7; j++) { + if (sample_freq & (1 << j)) { + if (sample_freq_num != 0) + len += sprintf(buf + len, + "|"); /* separator */ + switch (j) { + case 0: + len += sprintf(buf + len, "32KHz"); + break; + case 1: + len += sprintf(buf + len, "44KHz"); + break; + case 2: + len += sprintf(buf + len, "48KHz"); + break; + case 3: + len += sprintf(buf + len, "88KHz"); + break; + case 4: + len += sprintf(buf + len, "96KHz"); + break; + case 5: + len += sprintf(buf + len, "176KHz"); + break; + case 6: + len += sprintf(buf + len, "192KHz"); + break; + default: + break; + } + sample_freq_num++; + } + } + + if (sample_freq_num == 0) + len += sprintf(buf + len, "0"); + + /* separator */ + len += sprintf(buf + len, ","); + + /* + SAD Byte 3 (bitrate): + For LPCM, bits 7:3 are reserved and the remaining bits + define bit depth + bit 2: 24 bit + bit 1: 20 bit + bit 0: 16 bit + For all other sound formats, bits 7..0 designate the maximum + supported bitrate divided by 8 kbit/s. + */ + bitrate = edid_parsed.sad[i].sad_byte[2]; + bitrate_num = 0; + if (audio_format == 1) { /* for LPCM */ + for (j = 0; j < 3; j++) { + if (bitrate & (1 << j)) { + if (bitrate_num != 0) + len += sprintf(buf + len, + "|"); /* separator */ + switch (j) { + case 0: + len += sprintf(buf + len, + "16bit"); + break; + case 1: + len += sprintf(buf + len, + "20bit"); + break; + case 2: + len += sprintf(buf + len, + "24bit"); + break; + default: + break; + } + bitrate_num++; + } + } + } else if (audio_format >= 2 && + audio_format <= 8) /* From AC3 to ATRAC */ + len += sprintf(buf + len, "%dkbps", bitrate * 8); + else /* From One-bit-audio to WMA Pro*/ + len += sprintf(buf + len, "%d", bitrate); + + len += sprintf(buf + len, "\n"); + } + + if (len == 0) + len += sprintf(buf + len, "\n"); + + return len; +} + +static DEVICE_ATTR(edid_parsed, 0444, attr_show_parsed_edid, NULL); + +void vpp_switch_state_init(void) +{ + /* /sys/class/switch/hdmi/state */ + switch_dev_register(&vpp_sdev); + switch_set_state(&vpp_sdev, hdmi_get_plugin() ? 1 : 0); + switch_dev_register(&vpp_sdev_hdcp); + switch_set_state(&vpp_sdev_hdcp, 0); + switch_dev_register(&vpp_sdev_audio); + device_create_file(vpp_sdev.dev, &dev_attr_edid_parsed); +} + +void vpp_netlink_notify(int no, int cmd, int arg) +{ + int ret; + int size; + unsigned char *old_tail; + struct sk_buff *skb; + struct nlmsghdr *nlh; + struct vpp_netlink_proc_t *proc; + + proc = vpp_netlink_get_proc(no); + if (!proc) + return; + + MSG("[VPP] netlink notify %d,cmd %d,0x%x\n", no, cmd, arg); + + switch (cmd) { + case DEVICE_RX_DATA: + size = NLMSG_SPACE(sizeof(struct wmt_cec_msg)); + break; + case DEVICE_PLUG_IN: + case DEVICE_PLUG_OUT: + case DEVICE_STREAM: + size = NLMSG_SPACE(sizeof(struct wmt_cec_msg)); + break; + default: + return; + } + + skb = alloc_skb(size, GFP_ATOMIC); + if (skb == NULL) + return; + old_tail = skb->tail; + nlh = NLMSG_PUT(skb, 0, 0, 0, size-sizeof(*nlh)); + nlh->nlmsg_len = skb->tail - old_tail; + + switch (cmd) { + case DEVICE_RX_DATA: + nlh->nlmsg_type = DEVICE_RX_DATA; + memcpy(NLMSG_DATA(nlh), (struct wmt_cec_msg *)arg, + sizeof(struct wmt_cec_msg)); + break; + case DEVICE_PLUG_IN: + case DEVICE_PLUG_OUT: + { + static int cnt; + struct wmt_cec_msg *msg; + + msg = (struct wmt_cec_msg *)NLMSG_DATA(nlh); + msg->msgdata[0] = cnt; + cnt++; + } + if (arg) { + nlh->nlmsg_type = DEVICE_PLUG_IN; + nlh->nlmsg_flags = edid_get_hdmi_phy_addr(); + } else { + nlh->nlmsg_type = DEVICE_PLUG_OUT; + } + size = NLMSG_SPACE(sizeof(0)); + break; + case DEVICE_STREAM: + nlh->nlmsg_type = cmd; + nlh->nlmsg_flags = arg; + break; + default: + return; + } + + NETLINK_CB(skb).pid = 0; + NETLINK_CB(skb).dst_group = 0; + + if (proc->pid != 0) { + ret = netlink_unicast(vpp_nlfd, skb, proc->pid, MSG_DONTWAIT); + return; + } +nlmsg_failure: /* NLMSG_PUT go to */ + if (skb != NULL) + kfree_skb(skb); + return; +} + +void vpp_netlink_notify_plug(int vo_num, int plugin) +{ + /* set unplug flag for check_var */ + if (plugin == 0) { + int mask = 0; + + if (vo_num == VPP_VOUT_ALL) + mask = ~0; + else { + struct vout_info_t *vo_info; + vo_info = vout_get_info_entry(vo_num); + if (vo_info) + mask = 0x1 << (vo_info->num); + } + g_vpp.fb_recheck |= mask; + } + + if ((vpp_netlink_proc[0].pid == 0) && (vpp_netlink_proc[1].pid == 0)) + return; + + /* if hdmi unplug, clear edid_parsed */ + if (hdmi_get_plugin() == 0) + memset(&edid_parsed, 0, sizeof(struct edid_parsed_t)); + + vpp_netlink_notify(USER_PID, DEVICE_PLUG_IN, plugin); + vpp_netlink_notify(WP_PID, DEVICE_PLUG_IN, plugin); + + /* hdmi plugin/unplug */ + plugin = hdmi_get_plugin(); + switch_set_state(&vpp_sdev, plugin ? 1 : 0); + wmt_enable_mmfreq(WMT_MMFREQ_HDMI_PLUG, plugin); +} + +void vpp_netlink_notify_cp(int enable) +{ + switch_set_state(&vpp_sdev_hdcp, enable); +} +EXPORT_SYMBOL(vpp_netlink_notify_cp); + +#endif /* CONFIG_VPP_NOTIFY */ +#endif /* __KERNEL__ */ diff --git a/common/wmt_display/vpp.h b/common/wmt_display/vpp.h new file mode 100755 index 0000000..d960e2a --- /dev/null +++ b/common/wmt_display/vpp.h @@ -0,0 +1,679 @@ +/*++ + * linux/drivers/video/wmt/vpp.h + * WonderMedia video post processor (VPP) driver + * + * Copyright c 2014 WonderMedia Technologies, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * WonderMedia Technologies, Inc. + * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C +--*/ + +#include "vpp-osif.h" +#include "./hw/wmt-vpp-hw.h" +#include "com-vpp.h" +#ifdef CONFIG_KERNEL +#include "com-cec.h" +#endif +#include "vout.h" + +#ifndef VPP_H +#define VPP_H + +#define CONFIG_VPP_SHENZHEN /* for ShenZhen code */ + +/* VPP feature config */ +/* #define CONFIG_VPP_DEMO */ /* HDMI EDID, CP disable */ +#ifdef CONFIG_KERNEL +#define CONFIG_VPP_STREAM_CAPTURE /* stream capture current video display */ +#define CONFIG_VPP_STREAM_BLOCK +/* #define CONFIG_VPP_DISABLE_PM */ /* disable power management */ +#define CONFIG_VPP_VIRTUAL_DISPLAY /* virtual fb dev */ +#define CONFIG_VPP_NOTIFY +#endif +/* #define CONFIG_VPP_DYNAMIC_ALLOC */ /* frame buffer dynamic allocate */ + +/* VPP constant define */ +#define VPP_MB_ALLOC_NUM 3 +#define VPP_STREAM_MB_ALLOC_NUM (VPP_MB_ALLOC_NUM * 2) + +enum vpp_int_t { + VPP_INT_NULL = 0, + VPP_INT_ALL = 0xffffffff, + + VPP_INT_GOVRH_PVBI = BIT0, + VPP_INT_GOVRH_VBIS = BIT1, /* write done */ + VPP_INT_GOVRH_VBIE = BIT2, + + VPP_INT_GOVW_PVBI = BIT3, + VPP_INT_GOVW_VBIS = BIT4, + VPP_INT_GOVW_VBIE = BIT5, + + VPP_INT_DISP_PVBI = BIT6, + VPP_INT_DISP_VBIS = BIT7, + VPP_INT_DISP_VBIE = BIT8, + + VPP_INT_LCD_EOF = BIT9, + + VPP_INT_SCL_PVBI = BIT12, + VPP_INT_SCL_VBIS = BIT13, + VPP_INT_SCL_VBIE = BIT14, + + VPP_INT_VPU_PVBI = BIT15, + VPP_INT_VPU_VBIS = BIT16, + VPP_INT_VPU_VBIE = BIT17, + + VPP_INT_GOVRH2_PVBI = BIT18, + VPP_INT_GOVRH2_VBIS = BIT19, /* write done */ + VPP_INT_GOVRH2_VBIE = BIT20, + + VPP_INT_MAX = BIT31, + +}; + +enum vpp_int_err_t { + /* SCL */ + VPP_INT_ERR_SCL_TG = BIT0, + VPP_INT_ERR_SCLR1_MIF = BIT1, + VPP_INT_ERR_SCLR2_MIF = BIT2, + VPP_INT_ERR_SCLW_MIFRGB = BIT3, + VPP_INT_ERR_SCLW_MIFY = BIT4, + VPP_INT_ERR_SCLW_MIFC = BIT5, + + /* GOVRH2 */ + VPP_INT_ERR_GOVRH2_MIF = BIT19, + + /* GOVRH */ + VPP_INT_ERR_GOVRH_MIF = BIT20, + +}; + +/* VPP FB capability flag */ +#define VPP_FB_FLAG_COLFMT 0xFFFF +#define VPP_FB_FLAG_SCALE BIT(16) +#define VPP_FB_FLAG_CSC BIT(17) +#define VPP_FB_FLAG_MEDIA BIT(18) +#define VPP_FB_FLAG_FIELD BIT(19) + +struct vpp_fb_base_t { + vdo_framebuf_t fb; + vpp_csc_t csc_mode; + int framerate; + vpp_media_format_t media_fmt; + int wait_ready; + unsigned int capability; + + void (*set_framebuf)(vdo_framebuf_t *fb); + void (*get_framebuf)(vdo_framebuf_t *fb); + void (*set_addr)(unsigned int yaddr, unsigned int caddr); + void (*get_addr)(unsigned int *yaddr, unsigned int *caddr); + void (*set_csc)(vpp_csc_t mode); + vdo_color_fmt(*get_color_fmt)(void); + void (*set_color_fmt)(vdo_color_fmt colfmt); + void (*fn_view)(int read, vdo_view_t *view); +}; + +#define VPP_MOD_BASE \ + vpp_mod_t mod; /* module id*/\ + void *mmio; /* regs base address */\ + unsigned int int_catch; /* interrupt catch */\ + struct vpp_fb_base_t *fb_p; /* framebuf base pointer */\ + unsigned int pm; /* power dev id,bit31-0:power off */\ + unsigned int *reg_bk; /* register backup pointer */\ + void (*init)(void *base); /* module initial */\ + void (*dump_reg)(void); /* dump hardware register */\ + void (*set_enable)(vpp_flag_t enable); /* module enable/disable */\ + void (*set_colorbar)(vpp_flag_t enable, int mode, int inv); \ + /* hw colorbar enable/disable & mode */\ + void (*set_tg)(vpp_clock_t *tmr, unsigned int pixel_clock); /*set tg*/\ + void (*get_tg)(vpp_clock_t *tmr); /* get timing */\ + unsigned int (*get_sts)(void); /* get interrupt or error status */\ + void (*clr_sts)(unsigned int sts); /* clear interrupt or err status */\ + void (*suspend)(int sts); /* module suspend */\ + void (*resume)(int sts) /* module resume */ +/* End of vpp_mod_base_t */ + +struct vpp_mod_base_t { + VPP_MOD_BASE; +}; + +#define VPP_MOD_FLAG_FRAMEBUF BIT(0) +#define VPP_MOD_CLK_ON BIT(31) + +enum vpp_scale_mode_t { + VPP_SCALE_MODE_REC_TABLE, /* old design but 1/32 limit */ + VPP_SCALE_MODE_RECURSIVE, /*no rec table,not smooth than bilinear mode*/ + VPP_SCALE_MODE_BILINEAR,/*more smooth but less than 1/2 will drop line*/ + VPP_SCALE_MODE_ADAPTIVE,/* scl dn 1-1/2 bilinear mode, other rec mode */ + VPP_SCALE_MODE_MAX +}; + +enum vpp_hdmi_audio_inf_t { + VPP_HDMI_AUDIO_I2S, + VPP_HDMI_AUDIO_SPDIF, + VPP_HDMI_AUDIO_MAX +}; + +enum vpp_filter_mode_t { + VPP_FILTER_SCALE, + VPP_FILTER_DEBLOCK, + VPP_FILTER_FIELD_DEFLICKER, + VPP_FILTER_FRAME_DEFLICKER, + VPP_FILTER_MODE_MAX +}; + +#define VPP_DBG_PERIOD_NUM 10 +struct vpp_dbg_period_t { + int index; + int period_us[VPP_DBG_PERIOD_NUM]; + struct timeval pre_tv; +}; + +struct vpp_dbg_timer_t { + struct timeval pre_tv; + unsigned int threshold; + unsigned int reset; + unsigned int cnt; + unsigned int sum; + unsigned int min; + unsigned int max; +}; + +#ifdef __KERNEL__ +#define VPP_PROC_NUM 10 +struct vpp_proc_t { + int (*func)(void *arg); /* function pointer */ + void *arg; /* function argument */ + struct list_head list; + enum vpp_int_t type; /* interrupt type */ + struct semaphore sem; /* wait sem */ + int wait_ms; /* wait complete timout (ms) */ + int work_cnt; /* work counter if 0 then forever */ +}; + +struct vpp_irqproc_t { + struct list_head list; + struct tasklet_struct tasklet; + int ref; +}; +#endif + +#ifndef CFG_LOADER +#include "vppm.h" +#endif +#include "lcd.h" + +/* #ifdef WMT_FTBLK_SCL */ +#include "scl.h" +/* #endif */ +/* +#ifdef WMT_FTBLK_GE +#include "ge.h" +#endif +*/ +#ifdef WMT_FTBLK_GOVRH +#include "govrh.h" +#endif +#ifdef WMT_FTBLK_LVDS +#include "lvds.h" +#endif +/* #ifdef WMT_FTBLK_HDMI */ +#include "hdmi.h" +#ifndef CFG_LOADER +#include "cec.h" +#endif +/* #endif */ +#ifdef CONFIG_WMT_EDID +#include "edid.h" +#endif + +enum vpp_dbg_level_t { + VPP_DBGLVL_DISABLE = 0x0, + VPP_DBGLVL_SCALE = 1, + VPP_DBGLVL_DISPFB = 2, + VPP_DBGLVL_INT = 3, + VPP_DBGLVL_FPS = 4, + VPP_DBGLVL_IOCTL = 5, + VPP_DBGLVL_DIAG = 6, + VPP_DBGLVL_STREAM = 7, + VPP_DBGLVL_ALL = 0xFF, +}; + +struct vpp_info_t { + /* internal parameter */ + int govrh_preinit; + int virtual_display; + int fb0_bitblit; + int fb_manual; /* not check var & internel timing */ + int fb_recheck; /* recheck for plug but no change res */ + int govrh_init_yres; + int stream_fb; + + /* hdmi */ + enum vpp_hdmi_audio_inf_t hdmi_audio_interface; /* 0-I2S, 1-SPDIF */ + int hdmi_cp_enable; /* 0-off, 1-on */ + int hdmi_audio_channel; + int hdmi_audio_freq; + unsigned int hdmi_ctrl; + unsigned int hdmi_audio_pb1; + unsigned int hdmi_audio_pb4; + unsigned int hdmi_i2c_freq; + unsigned int hdmi_i2c_udelay; + int hdmi_init; + unsigned int hdmi_bksv[2]; + char *hdmi_cp_p; + int hdmi_3d_type; + unsigned int hdmi_pixel_clock; + int hdmi_certify_flag; + int hdmi_sp_mode; + int hdmi_disable; + int hdmi_ch_change; + + /* alloc frame buffer */ + int mb_colfmt; + + /* debug */ + int dbg_msg_level; /* debug message level */ + int dbg_wait; + int dbg_flag; + + /* dvi */ + int dvi_int_disable; + int dvi_int_no; /* DVO external board interrupt use GPIOxx */ + int dvi_i2c_no; /* DVO external board i2c bus id */ + +#if 0 + /* HDMI DDC debug */ + int dbg_hdmi_ddc_ctrl_err; + int dbg_hdmi_ddc_read_err; + int dbg_hdmi_ddc_crc_err; +#endif + +#ifdef CONFIG_VPP_STREAM_CAPTURE + /* stream capture current video display */ + int stream_enable; + unsigned int stream_mb_lock; + int stream_mb_sync_flag; + int stream_mb_index; + unsigned int stream_mb[VPP_STREAM_MB_ALLOC_NUM]; + int stream_mb_cnt; + unsigned int stream_sync_cnt; +#endif +}; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef VPP_C +#define EXTERN + +const unsigned int vpp_csc_parm[VPP_CSC_MAX][7] = { + /* C1,C2 C3,C4 C5,C6 C7,C8 C9,I + J,K b0:YC2RGB,b8:clamp */ + {0x000004a8, 0x04a80662, 0x1cbf1e70, 0x081204a8, 0x00010000, + 0x00010001, 0x00000101}, /* YUV2RGB_SDTV_0_255 */ + {0x00000400, 0x0400057c, 0x1d351ea8, 0x06ee0400, 0x00010000, + 0x00010001, 0x00000001}, /* YUV2RGB_SDTV_16_235 */ + {0x000004a8, 0x04a8072c, 0x1ddd1f26, 0x087604a8, 0x00010000, + 0x00010001, 0x00000101}, /* YUV2RGB_HDTV_0_255 */ + {0x00000400, 0x04000629, 0x1e2a1f45, 0x07440400, 0x00010000, + 0x00010001, 0x00000001}, /* YUV2RGB_HDTV_16_235 */ + {0x00000400, 0x0400059c, 0x1d251ea0, 0x07170400, 0x00010000, + 0x00010001, 0x00000001}, /* YUV2RGB_JFIF_0_255 */ + {0x00000400, 0x0400057c, 0x1d351ea8, 0x06ee0400, 0x00010000, + 0x00010001, 0x00000001}, /* YUV2RGB_SMPTE170M */ + {0x00000400, 0x0400064d, 0x1e001f19, 0x074f0400, 0x00010000, + 0x00010001, 0x00000001}, /* YUV2RGB_SMPTE240M */ + {0x02040107, 0x1f680064, 0x01c21ed6, 0x1e8701c2, 0x00211fb7, + 0x01010101, 0x00000000}, /* RGB2YUV_SDTV_0_255 */ + {0x02590132, 0x1f500075, 0x020b1ea5, 0x1e4a020b, 0x00011fab, + 0x01010101, 0x00000000}, /* RGB2YUV_SDTV_16_235 */ + {0x027500bb, 0x1f99003f, 0x01c21ea6, 0x1e6701c2, 0x00211fd7, + 0x01010101, 0x00000000}, /* RGB2YUV_HDTV_0_255 */ + {0x02dc00da, 0x1f88004a, 0x020b1e6d, 0x1e25020b, 0x00011fd0, + 0x01010101, 0x00000000}, /* RGB2YUV_HDTV_16_235 */ + {0x02590132, 0x1f530075, 0x02001ead, 0x1e530200, 0x00011fad, + 0x01010101, 0x00000000}, /* RGB2YUV_JFIF_0_255 */ + {0x02590132, 0x1f500075, 0x020b1ea5, 0x1e4a020b, 0x00011fab, + 0x01010101, 0x00000000}, /* RGB2YUV_SMPTE170M */ + {0x02ce00d9, 0x1f890059, 0x02001e77, 0x1e380200, 0x00011fc8, + 0x01010101, 0x00000000}, /* RGB2YUV_SMPTE240M */ + {0x02780142, 0x1e80007a, 0x04711d0e, 0x1c470471, 0x00001f46, + 0x01010101, 0x00000000} /* RGB2YUV_JFIF_VT1625 */ +}; + +const struct fb_videomode vpp_videomode[] = { + /* 640x480@60 DMT/CEA861 */ + { NULL, 60, 640, 480, KHZ2PICOS(25175), 48, 16, 33, 10, 96, 2, + 0, FB_VMODE_NONINTERLACED, 0}, +#if 0 + /* 640x480@60 CVT */ + { NULL, 60, 640, 480, KHZ2PICOS(23750), 80, 16, 13, 3, 64, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 640x480@75 DMT */ + { NULL, 75, 640, 480, KHZ2PICOS(31500), 120, 16, 16, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 640x480@75 CVT */ + { NULL, 75, 640, 480, KHZ2PICOS(30750), 88, 24, 17, 3, 64, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 720x480@60 CEA861 */ + { NULL, 60, 720, 480, KHZ2PICOS(27027), 60, 16, 30, 9, 62, 6, + 0, FB_VMODE_NONINTERLACED, 0}, + /* 720x480i@60 CEA861 */ + { NULL, 60, 720, 480, KHZ2PICOS(27000), 114, 38, 30, 8, 124, 6, + 0, FB_VMODE_INTERLACED + FB_VMODE_DOUBLE, 0}, + /* 720x576@50 CEA861 */ + { NULL, 50, 720, 576, KHZ2PICOS(27000), 68, 12, 39, 5, 64, 5, + 0, FB_VMODE_NONINTERLACED, 0}, + /* 720x576i@50 CEA861 */ + { NULL, 50, 720, 576, KHZ2PICOS(27000), 138, 24, 38, 4, 126, 6, + 0, FB_VMODE_INTERLACED + FB_VMODE_DOUBLE, 0}, + /* 800x480@60 CVT */ + { NULL, 60, 800, 480, KHZ2PICOS(29500), 96, 24, 10, 3, 72, 7, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 800x480@75 CVT */ + { NULL, 75, 800, 480, KHZ2PICOS(38500), 112, 32, 14, 3, 80, 7, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 800x600@60 DMT */ + { NULL, 60, 800, 600, KHZ2PICOS(40000), 88, 40, 23, 1, 128, 4, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 800x600@60 CVT */ + { NULL, 60, 800, 600, KHZ2PICOS(38250), 112, 32, 17, 3, 80, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 800x600@75 DMT */ + { NULL, 75, 800, 600, KHZ2PICOS(49500), 160, 16, 21, 1, 80, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 800x600@75 CVT */ + { NULL, 75, 800, 600, KHZ2PICOS(49000), 120, 40, 22, 3, 80, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 848x480@60 DMT */ + { NULL, 60, 848, 480, KHZ2PICOS(33750), 112, 16, 23, 6, 112, 8, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1024x600@60 DMT */ + { NULL, 60, 1024, 600, KHZ2PICOS(49000), 144, 40, 11, 3, 104, 10, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1024x768@60 DMT */ + { NULL, 60, 1024, 768, KHZ2PICOS(65000), 160, 24, 29, 3, 136, 6, + 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1024x768@60 CVT */ + { NULL, 60, 1024, 768, KHZ2PICOS(63500), 152, 48, 23, 3, 104, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 1024x768@75 DMT */ + { NULL, 75, 1024, 768, KHZ2PICOS(78750), 176, 16, 28, 1, 96, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 1024x768@75 CVT */ + { NULL, 75, 1024, 768, KHZ2PICOS(82000), 168, 64, 30, 3, 104, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 1152x864@60 CVT */ + { NULL, 60, 1152, 864, KHZ2PICOS(81750), 184, 64, 26, 3, 120, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 1152x864@75 DMT */ + { NULL, 75, 1152, 864, KHZ2PICOS(108000), 256, 64, 32, 1, 128, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1152x864@75 CVT */ + { NULL, 75, 1152, 864, KHZ2PICOS(104000), 192, 72, 34, 3, 120, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 1280x720@50 CEA861,HDMI_1280x720p50_16x9 */ + { NULL, 50, 1280, 720, KHZ2PICOS(74250), 220, 440, 20, 5, 40, 5, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1280x720@60 CEA861,HDMI_1280x720p60_16x9 */ + { NULL, 60, 1280, 720, KHZ2PICOS(74250), 220, 110, 20, 5, 40, 5, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, +#if 0 + /* 1280x720@60 CVT */ + { NULL, 60, 1280, 720, KHZ2PICOS(74500), 192, 64, 20, 3, 128, 5, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 1280x720@75 CVT */ + { NULL, 75, 1280, 720, KHZ2PICOS(95750), 208, 80, 27, 3, 128, 5, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 1280x768@60 DMT/CVT */ + { NULL, 60, 1280, 768, KHZ2PICOS(79500), 192, 64, 20, 3, 128, 7, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1280x768@75 DMT/CVT */ + { NULL, 75, 1280, 768, KHZ2PICOS(102250), 208, 80, 27, 3, 128, 7, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1280x800@60 DMT/CVT */ + { NULL, 60, 1280, 800, KHZ2PICOS(83500), 200, 72, 22, 3, 128, 6, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1280x800@75 DMT/CVT */ + { NULL, 75, 1280, 800, KHZ2PICOS(106500), 208, 80, 29, 3, 128, 6, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1280x960@60 DMT */ + { NULL, 60, 1280, 960, KHZ2PICOS(108000), 312, 96, 36, 1, 112, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 1280x960@60 CVT */ + { NULL, 60, 1280, 960, KHZ2PICOS(101250), 208, 80, 29, 3, 128, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 1280x960@75 CVT */ + { NULL, 75, 1280, 960, KHZ2PICOS(130000), 224, 88, 38, 3, 136, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, + /* 1280x1024@60 DMT */ + { NULL, 60, 1280, 1024, KHZ2PICOS(108000), 248, 48, 38, 1, 112, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 1280x1024@60 CVT */ + { NULL, 60, 1280, 1024, KHZ2PICOS(109000), 216, 80, 29, 3, 136, 7, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 1280x1024@75 DMT */ + { NULL, 75, 1280, 1024, KHZ2PICOS(135000), 248, 16, 38, 1, 144, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 1280x1024@75 CVT */ + { NULL, 75, 1280, 1024, KHZ2PICOS(138750), 224, 88, 38, 3, 136, 7, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0}, +#endif + /* 1360x768@60 */ + { NULL, 60, 1360, 768, KHZ2PICOS(85500), 256, 64, 18, 3, 112, 6, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1366x768@60 */ + { NULL, 60, 1366, 768, KHZ2PICOS(85500), 213, 70, 24, 3, 143, 3, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1400x1050@60 DMT/CVT */ + { NULL, 60, 1400, 1050, KHZ2PICOS(121750), 232, 88, 32, 3, 144, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#if 0 + /* 1400x1050@60+R DMT/CVT */ + { NULL, 60, 1400, 1050, KHZ2PICOS(101000), 80, 48, 23, 3, 32, 4, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, +#endif + /* 1440x480p@60 CEA861 */ + { NULL, 60, 1400, 480, KHZ2PICOS(54054), 120, 32, 30, 9, 124, 6, + 0, FB_VMODE_NONINTERLACED, 0}, + /* 1440x900@60 DMT/CVT */ + { NULL, 60, 1440, 900, KHZ2PICOS(106500), 232, 80, 25, 3, 152, 6, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1440x900@75 DMT/CVT */ + { NULL, 75, 1440, 900, KHZ2PICOS(136750), 248, 96, 33, 3, 152, 6, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1600x1200@60 DMT/CVT */ + { NULL, 60, 1600, 1200, KHZ2PICOS(162000), 304, 64, 46, 1, 192, 3, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1680x1050@60 DMT/CVT */ + { NULL, 60, 1680, 1050, KHZ2PICOS(146250), 280, 104, 30, 3, 176, 6, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1920x1080@25,HDMI_1920x1080p25_16x9 */ + { NULL, 25, 1920, 1080, KHZ2PICOS(74250), 148, 528, 36, 4, 44, 5, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1920x1080@30,HDMI_1920x1080p30_16x9 */ + { NULL, 30, 1920, 1080, KHZ2PICOS(74250), 148, 88, 36, 4, 44, 5, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1920x1080@50,HDMI_1920x1080p50_16x9 */ + { NULL, 50, 1920, 1080, KHZ2PICOS(148500), 148, 528, 36, 4, 44, 5, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1920x1080i@50 */ + { NULL, 50, 1920, 1080, KHZ2PICOS(74250), 148, 528, 30, 4, 44, 10, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_INTERLACED, 0}, + /* 1920x1080@60 */ + { NULL, 60, 1920, 1080, KHZ2PICOS(148500), 148, 88, 36, 4, 44, 5, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0}, + /* 1920x1080i@60 */ + { NULL, 60, 1920, 1080, KHZ2PICOS(74250), 148, 88, 30, 4, 44, 10, + FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_INTERLACED, 0}, + /* 1920x1200@60+R DMT/CVT */ + { NULL, 60, 1920, 1200, KHZ2PICOS(154000), 80, 48, 26, 3, 32, 6, + FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + /* 1920x1200@60 DMT/CVT */ + { NULL, 60, 1920, 1200, KHZ2PICOS(193250), 336, 136, 36, 3, 200, 6, + FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA}, + { NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0 }, +}; + +char *vpp_colfmt_str[] = {"YUV420", "YUV422H", "YUV422V", "YUV444", "YUV411", + "GRAY", "ARGB", "AUTO", "RGB888", "RGB666", "RGB565", + "RGB1555", "RGB5551"}; +const char *vpp_mod_str[] = {"GOVRH2", "GOVRH", "DISP", "GOVW", "GOVM", "SCL", + "SCLW", "VPU", "VPUW", "PIP", "VPPM", "LCDC", "CUR", "MAX"}; + +#else +#define EXTERN extern + +extern const unsigned int vpp_csc_parm[VPP_CSC_MAX][7]; +extern char *vpp_colfmt_str[]; +extern const struct fb_videomode vpp_videomode[]; +extern char *vpp_mod_str[]; +#ifdef CONFIG_VPP_NOTIFY +extern struct switch_dev vpp_sdev; +#endif +#endif + +EXTERN struct vpp_info_t g_vpp; +#ifdef VPP_C +EXPORT_SYMBOL(g_vpp); +#endif + +static inline int vpp_get_hdmi_spdif(void) +{ + return (g_vpp.hdmi_audio_interface == VPP_HDMI_AUDIO_SPDIF) ? 1 : 0; +} + +/* Internal functions */ +EXTERN int get_key(void); +EXTERN unsigned int vpp_get_chipid(void); + +/* Export functions */ +EXTERN void vpp_mod_unregister(vpp_mod_t mod); +EXTERN struct vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod, int size, + unsigned int flags); +EXTERN struct vpp_mod_base_t *vpp_mod_get_base(vpp_mod_t mod); +EXTERN struct vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod); +EXTERN vdo_framebuf_t *vpp_mod_get_framebuf(vpp_mod_t mod); +EXTERN void vpp_mod_init(void); +EXTERN void vpp_mod_set_clock(vpp_mod_t mod, + vpp_flag_t enable, int force); + +EXTERN unsigned int vpp_get_base_clock(vpp_mod_t mod); +EXTERN void vpp_set_video_scale(vdo_view_t *vw); +EXTERN int vpp_set_recursive_scale(vdo_framebuf_t *src_fb, + vdo_framebuf_t *dst_fb); +EXTERN vpp_display_format_t vpp_get_fb_field(vdo_framebuf_t *fb); +EXTERN void vpp_wait_vsync(int no, int cnt); +EXTERN int vpp_get_gcd(int A, int B); +EXTERN vpp_csc_t vpp_check_csc_mode(vpp_csc_t mode, + vdo_color_fmt src_fmt, vdo_color_fmt dst_fmt, unsigned int flags); +EXTERN inline void vpp_cache_sync(void); +EXTERN int vpp_calc_refresh(int pixclk, int xres, int yres); +EXTERN int vpp_calc_align(int value, int align); +EXTERN int vpp_calc_fb_width(vdo_color_fmt colfmt, int width); +EXTERN void vpp_get_colfmt_bpp(vdo_color_fmt colfmt, + int *y_bpp, int *c_bpp); +EXTERN int vpp_irqproc_work(enum vpp_int_t type, int (*func)(void *argc), + void *arg, int wait_ms, int work_cnt); +EXTERN int vpp_check_dbg_level(enum vpp_dbg_level_t level); + +#ifdef __KERNEL__ +EXTERN void vpp_dbg_show(int level, int tmr, char *str); +EXTERN void vpp_dbg_wake_up(void); +EXTERN int vpp_dbg_get_period_usec(struct vpp_dbg_period_t *p, + int cmd); +EXTERN void vpp_dbg_timer(struct vpp_dbg_timer_t *p, char *str, int cmd); +EXTERN void vpp_dbg_back_trace(void); +EXTERN void vpp_dbg_show_val1(int level, int tmr, char *str, int val); +EXTERN void vpp_dbg_wait(char *str); +EXTERN void vpp_irqproc_init(void); +EXTERN void vpp_irqproc_del_work(enum vpp_int_t type, + int (*func)(void *argc)); +EXTERN struct vpp_irqproc_t *vpp_irqproc_get_entry( + enum vpp_int_t vpp_int); + +/* dev-vpp.c */ +EXTERN int vpp_get_info(int fbn, struct fb_var_screeninfo *var); +EXTERN int vpp_set_par(struct fb_info *info); +EXTERN void vpp_backup_reg2(unsigned int addr, + unsigned int size, unsigned int *ptr); +EXTERN void vpp_restore_reg2(unsigned int addr, + unsigned int size, unsigned int *reg_ptr); +EXTERN int vpp_pan_display(struct fb_var_screeninfo *var, + struct fb_info *info); +EXTERN void vpp_netlink_init(void); +EXTERN void vpp_netlink_notify(int no, int cmd, int arg); +EXTERN void vpp_netlink_notify_plug(int vout_num, int plugin); +EXTERN void vpp_netlink_notify_cp(int enable); +EXTERN void vpp_switch_state_init(void); +EXTERN int vpp_set_blank(struct fb_info *info, int blank); +#endif + +EXTERN unsigned int vpp_convert_colfmt(int yuv2rgb, unsigned int data); +EXTERN void vpp_init(void); + +/* EXTERN void vpp_set_power_mgr(int arg); */ +EXTERN void vpp_show_timing(char *str, + struct fb_videomode *vmode, vpp_clock_t *clk); +EXTERN void vpp_show_framebuf(char *str, vdo_framebuf_t *fb); +EXTERN void vpp_show_videomode(char *str, struct fb_videomode *v); +EXTERN void vpp_set_NA12_hiprio(int type); + +EXTERN int vpp_mb_get(unsigned int phy); +EXTERN int vpp_mb_put(unsigned int phy); +EXTERN int vpp_mb_irqproc_sync(int arg); + +#undef EXTERN + +#ifdef __cplusplus +} +#endif +#endif /* VPP_H */ diff --git a/common/wmt_display/wmt-ost.c b/common/wmt_display/wmt-ost.c new file mode 100755 index 0000000..92b8417 --- /dev/null +++ b/common/wmt_display/wmt-ost.c @@ -0,0 +1,107 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ +#include <common.h> +#include "vpp.h" + +static WMT_OST_REG *pWMTOST; + +#ifndef NULL +#define NULL 0 +#endif + +int wmt_write_ostc(void) +{ + unsigned int sw_counter = 30000; + + while( pWMTOST->ostas & 0x10 ) { + if ( --sw_counter == 0 ) { // Need to be considered + printf("Count Write Active Busy\n"); + return -1; + } + } + return 0; +} + +int wmt_init_ost(void) +{ + //printf("wmt_init_ostimer\n"); + + if (pWMTOST == NULL) + pWMTOST = (WMT_OST_REG *)0xd8130100; + + if (pWMTOST->ostctrl&0x01) + return 0; + + pWMTOST->ostctrl = 0; + pWMTOST->ostwe = 0; + + if (wmt_write_ostc()) + return -1; + + pWMTOST->ostct = 0; + + pWMTOST->ostctrl = 1; + + return 0; +} + +int wmt_read_ostc(int *val) +{ + unsigned int sw_counter = 300000; + + if (pWMTOST == NULL) { + if (wmt_init_ost()) + return -1; + } + + if ( (pWMTOST->ostctrl & 0x02 ) == 0 ) + pWMTOST->ostctrl |= 0x02; + + // Check OS Timer Count Value is Valid + while ( (pWMTOST->ostas & 0x20) == 0x20 ) { + if ( --sw_counter == 0 ) { // Need to be considered + printf("Read Count Request Fail\n"); + break; + } + } + //*val = (int)pWMTOST->ostct; //Charles + *val = (int)pWMTOST->ostct/3; + return 0; +} + +int wmt_delayus(int us) +{ + int count = 100; + int before,after; + + //us = us*3; + + if (wmt_read_ostc(&before)) + return -1; + while(1) { + while(--count); + if (wmt_read_ostc(&after)) + return -1; + if ((after - before) >= us) { + //printf("request = %d , result = %d\n",us,(after - before)); + break; + } + count = 100; + } + return 0; +} + diff --git a/common/wmt_display/wmt_cmd_display.c b/common/wmt_display/wmt_cmd_display.c new file mode 100755 index 0000000..966972c --- /dev/null +++ b/common/wmt_display/wmt_cmd_display.c @@ -0,0 +1,357 @@ +/*++ +Copyright (c) 2014 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <linux/stddef.h> +#include <asm/byteorder.h> + +#include "vpp.h" +#include "wmt_display.h" +#include "minivgui.h" +#include "hw/wmt-pwm.h" +#include "../../board/wmt/include/wmt_iomux.h" + +extern int text_x, text_y; +extern void lcd_blt_enable(int no, int enable); +extern void *arm_memset(void *s, int c, size_t count); +extern void lcd_spi_setup(void); + +int display_init(int on, int force) +{ + struct vout_t *vo; + int i; + + if ((g_display_vaild & DISPLAY_ENABLE) == DISPLAY_ENABLE) { + if (force) { // force re-initial + if (g_display_param.vout == VPP_VOUT_LCD) + lcd_blt_enable(g_pwm_setting.pwm_no, 0); + // govrh_set_dvo_enable(VPP_FLAG_DISABLE); + // govrh_set_tg_enable(VPP_FLAG_DISABLE); + for (i = 0; i < VPP_VOUT_NUM; i++) { + vo = vout_get_entry(i); + if (!vo) + continue; + vout_set_blank(i, VOUT_BLANK_POWERDOWN); + } + + if (g_display_param.vout == VPP_VOUT_DVI) + //Wait for 500ms to let the TV's CVBS signal disconnect. It can avoid to the screen scratch + mdelay(500); + + g_display_vaild = 0; + } + } else + force = 1; + + if (force) { + if (wmt_graphic_init()) { + printf("wmt_graphic_init failed\n"); + return -1; + } else + printf("wmt_graphic_init ok\n"); + + text_x = 30; + text_y = 30 - CHAR_HEIGHT; + + lcd_spi_setup(); + } + + if ((g_display_param.vout == VPP_VOUT_LCD) && (on != 0)) { + printf("before lcd_blt_enable !!!!!!!!!\n"); + lcd_blt_enable(g_pwm_setting.pwm_no, 1); + printf("lcd_blt_enable !!!!!!!!!\n"); + } + + return 0; +} + +static void framebuffer_clean(void) +{ + int no; + mv_surface *s; + + for(no = 0; no < VPP_VOUT_INFO_NUM; no++) { + s = mv_getSurface(no); + if(s->startAddr) + arm_memset(s->startAddr, 0, s->height * s->lineBytes); + } +} + +int display_clear(void) +{ + if (g_display_vaild & DISPLAY_ENABLE) { + framebuffer_clean(); + return 0; + } else + return display_init(1, 0); +} + +int display_show(int clearFB) +{ + struct vout_info_t *info; + mv_surface *s; + int i; + + if (g_img_phy == 0xFFFF) { + printf("%s is not found , command (display show) is invaild\n", ENV_IMGADDR); + return -1; + } + if (display_init(0, 0)) + return -1; + + printf("Loading BMP .....\n"); + + g_logo_scale = (g_vpp.virtual_display) ? LOGO_MODE_MAX : LOGO_NOT_SCALE; + + //Becuase the logo scale has bug in portrait screen, don't scale logo when screen is portrait + //Fix it in the future + if(g_display_direction == 0 || g_display_direction == 2) + g_logo_scale = LOGO_NOT_SCALE; + + for (i = 0; i < VPP_VOUT_INFO_NUM; i++) { + info = vout_info[i]; + if (!info) + break; + if(g_logo_scale == LOGO_NOT_SCALE) { + if (mv_loadBmp(i, (unsigned char *)g_img_phy, clearFB)) { + printf("failed\r\n"); + return -1; + } + continue; + } + /* sclae logo */ + s = mv_getSurface(i); + if (s->startAddr) { + vdo_framebuf_t src_fb, *dst_fb; + unsigned int logo_addr = (unsigned int)s->startAddr; + int line_bytes = s->lineBytes; + + s->startAddr = (char *)(logo_addr - 1920 * 1080 * 4); + s->lineBytes = 1920 * 4; + s->width = 1920; + s->height = 1080; + if (mv_loadBmp(i, (unsigned char *)g_img_phy, clearFB)) { + printf("failed\r\n"); + return -1; + } + memset(&src_fb, 0, sizeof(vdo_framebuf_t)); + src_fb.col_fmt = (s->bits_per_pixel == 16) ? + VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB; + src_fb.img_w = s->img_width; + src_fb.img_h = s->img_height; + src_fb.fb_w = s->lineBytes / (s->bits_per_pixel / 8); + src_fb.fb_h = s->img_height; + src_fb.y_addr = (unsigned int)s->img_startAddr; + dst_fb = &info->fb; + vpp_set_recursive_scale(&src_fb, dst_fb); + + /* recover startAddr and lineBytes */ + s->startAddr = (char *)logo_addr; + s->lineBytes = line_bytes; + } + } + printf("Load Ok\n"); + if (g_display_param.vout == VPP_VOUT_LCD) { + lcd_blt_enable(g_pwm_setting.pwm_no, 1); + //lcd_uboot_set_backlight(); + } + return 0; +} + +int display_animation(unsigned int img_phy_addr) +{ + g_logo_x = -1; + g_logo_y = -1; + if (display_init(0, 0)) + return -1; + if (mv_loadBmp(0, (unsigned char *)img_phy_addr, 1)) { + printf("failed\r\n"); + return -1; + } + if (mv_loadBmp(1, (unsigned char *)img_phy_addr, 1)) { + printf("failed\r\n"); + return -1; + } + if (g_display_param.vout == VPP_VOUT_LCD) + lcd_blt_enable(g_pwm_setting.pwm_no, 1); + return 0; +} + +static int display_set_pwm(char *val, int on) +{ + + if (val == NULL) { + printf("error : can not get pwm parameter\n"); + return -1; + } + + lcd_blt_enable(g_pwm_setting.pwm_no, 0); + + parse_pwm_params(NULL, val); + + if ((g_display_vaild & PWMDEFMASK) == PWMDEFTP) { + lcd_blt_set_pwm(g_pwm_setting.pwm_no, g_pwm_setting.duty, g_pwm_setting.period); + } else { + // fan : may need to check PWM power .. + pwm_set_period(g_pwm_setting.pwm_no, g_pwm_setting.period - 1); + pwm_set_duty(g_pwm_setting.pwm_no, g_pwm_setting.duty - 1); + pwm_set_control(g_pwm_setting.pwm_no, (g_pwm_setting.duty - 1) ? 0x35 : 0x8); + pwm_set_gpio(g_pwm_setting.pwm_no, g_pwm_setting.duty - 1); + pwm_set_scalar(g_pwm_setting.pwm_no, g_pwm_setting.scalar - 1); + } + + lcd_blt_enable(g_pwm_setting.pwm_no, on); + + return 0; +} + +static int wmt_display_main (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int tmp; + + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + default: + if (strncmp(argv[1], "init", 2) == 0) { + if (argc == 3) { + if (strcmp(argv[2], "force") == 0) { + display_init(1, 1); + return 0; + } + } + display_init(1, 0); + return 0; + } + + if (strncmp(argv[1], "clear", 2) == 0) { + display_clear(); + return 0; + } + + if (strncmp(argv[1], "show", 2) == 0) { + if (4 == argc) { + g_logo_x = simple_strtoul(argv[2], NULL, 10); + g_logo_y = simple_strtoul(argv[3], NULL, 10); + printf("(%d, %d) ", g_logo_x, g_logo_y); + } else { + g_logo_x = -1; + g_logo_y = -1; + } + display_show(1); + return 0; + } + + if (strncmp(argv[1], "setpwm", 2) == 0) { + if (argc == 3) { + if (argv[2] != NULL) { + display_set_pwm(argv[2], 1); + return 0; + } + } else if (argc == 4) { + tmp = simple_strtoul(argv[2], NULL, 10); + if (argv[3] != NULL) { + display_set_pwm(argv[3], tmp); + return 0; + } + } + } + + if (!strncmp(argv[1], "backlight", 2)) { + if (!strncmp(argv[2], "on", 2)) + lcd_backlight_power_on(1); + else + lcd_backlight_power_on(0); + return 0; + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 0; + + } +} + +U_BOOT_CMD( + display, 5, 1, wmt_display_main, + "show - \n", + NULL +); + +static int do_avdetect(cmd_tbl_t *cmd, int flag, int argc, char *argv[]) +{ + int ret; + struct gpio_param_t avdetect_gpio; + + ret = parse_gpio_param("wmt.io.avdetect", &avdetect_gpio); + if(ret) { + DPRINT("please set wmt.io.avdetect\n"); + return -1; + } + + if(avdetect_gpio.gpiono > 19) { + DPRINT("invalid avdetect gpio no: %d\n", avdetect_gpio.gpiono); + return -1; + } + + gpio_direction_input(avdetect_gpio.gpiono); + gpio_setpull(avdetect_gpio.gpiono, GPIO_PULL_UP); + mdelay(10); + + if (avdetect_gpio.act) { + if(gpio_get_value(avdetect_gpio.gpiono)) + DPRINT("av plug in\n"); + else + DPRINT("av plug out\n"); + } else { + if(gpio_get_value(avdetect_gpio.gpiono)) + DPRINT("av plug out\n"); + else + DPRINT("av plug in\n"); + } + + return 0; +} + +U_BOOT_CMD( + avdetect, 1, 0, do_avdetect, + "avdetect - print AV in/out status\n", + "" +); + +static int do_dumphdmi(cmd_tbl_t *cmd, int flag, int argc, char *argv[]) +{ + p_govrh->dump_reg(); + p_govrh2->dump_reg(); + hdmi_reg_dump(); + + return 0; +} + +U_BOOT_CMD( + dumphdmi, 1, 0, do_dumphdmi, + "dumphdmi - dump govrh,govrh2 and hdmi register\n", + "" +); + diff --git a/common/wmt_display/wmt_display.h b/common/wmt_display/wmt_display.h new file mode 100755 index 0000000..85a7310 --- /dev/null +++ b/common/wmt_display/wmt_display.h @@ -0,0 +1,170 @@ +/*++ +Copyright (c) 2010 WonderMedia Technologies, Inc. + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. You +should have received a copy of the GNU General Public License along with this +program. If not, see http://www.gnu.org/licenses/>. + +WonderMedia Technologies, Inc. +4F, 531, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. +--*/ + +#ifndef __WM_LOGO_H__ +#define __WM_LOGO_H__ + +#include "vpp.h" + +typedef struct +{ + int width; + int height; + int lineBytes; + unsigned int bits_per_pixel; + char * startAddr; + + int img_width; + int img_height; + char *img_startAddr; +}mv_surface; + +typedef struct +{ + int left; + int top; + int right; + int bottom; +}mv_Rect; + + +#define ENV_DISPLAY_PARM "wmt.display.param" +#define ENV_DISPLAY_PARM2 "wmt.display.param2" +#define ENV_DISPLAY_TMR "wmt.display.tmr" +#define ENV_DISPLAY_PWM "wmt.display.pwm" +#define ENV_MEMTOTAL "memtotal" +#define ENV_IMGADDR "wmt.display.logoaddr" +#define ENV_LCD_POWERON "wmt.lcd.poweron" +#define ENV_DIRECTPATH "wmt.display.direct_path" +#define ENV_DIRECTFB "wmt.display.fb" +#define ENV_PMEM "wmt.pmem.param" +#define ENV_LCD_POWER "wmt.gpo.lcd" +#define ENV_POWER_LED "wmt.gpo.pwrled" +#define ENV_LOGO_LED_CONTROL "wmt.gpo.logoled" +#define ENV_CHARGE_ANIMATION "wmt.display.chargeanim" + +struct wmt_display_param_t { + unsigned int vout; + unsigned int op1; + unsigned int op2; + unsigned int resx; + unsigned int resy; + unsigned int fps_pixclk; +}; + +struct wmt_pwm_setting_t { + unsigned int pwm_no; + unsigned int scalar; + unsigned int period; + unsigned int duty; + unsigned int config; +}; + +struct gpio_operation_t { + unsigned int id; + unsigned int gpiono; + unsigned int act; + unsigned int bitmap; + unsigned int ctl; + unsigned int oc; + unsigned int od; +}; + +struct gpio_param_t { + unsigned int flag; + unsigned int gpiono; + unsigned int act; +}; + +struct wmt_backlight_param_t { + int pwm_no; + int invert; + int gpio; /* switch */ + int active; +}; + +typedef enum { + LOGO_NOT_SCALE, + LOGO_ORI_SCALE_FULL, // Put the logo to a buffer which size is logo original size, and then scale the buffer to full screen + LOGO_720P_SCALE_FULL, // Put the logo to the center of a buffer which size is 720p, and then scale the buffer to full screen + LOGO_MODE_MAX +} logo_scale_t; + +#ifdef WMT_DISPLAY +#define EXTERN +#else +#define EXTERN extern +#endif + +EXTERN struct wmt_display_param_t g_display_param; +EXTERN struct wmt_display_param_t g_display_param2; +EXTERN struct wmt_pwm_setting_t g_pwm_setting; +EXTERN struct gpio_operation_t g_lcd_pw_pin; +EXTERN unsigned int g_fb_phy; +EXTERN unsigned int g_img_phy; +EXTERN int g_logo_x; +EXTERN int g_logo_y; +EXTERN logo_scale_t g_logo_scale; + +#ifdef CONFIG_VPP_SHENZHEN +EXTERN struct wmt_backlight_param_t g_backlight_param; +#endif + +/* + 0 : not initial + not 0 : + bit 0 : + 1 : initial ok + 0 : not initial + bit1 : + 1 : get tmr from env + 0 : get tmr auto + bit[2:3] : + 00 : run pwm default (freq, level) + 01 : run pwm from env (freq, level) + 10 : run pwm from env (scalar, period, duty) + 11 : mask for pwm env config +*/ +EXTERN int g_display_vaild; + +#define DISPLAY_ENABLE 1 +#define TMRFROMENV 1<<1 +#define PWMDEFTP 1<<2 +#define PWMDEFSZ 1<<3 +#define PWMDEFMASK 0x0c + +// cmd_textout +#define CHAR_WIDTH 12 +#define CHAR_HEIGHT 22 // 16 + +int display_init(int on, int force); +int parse_display_tmr(char *name); +int parse_pwm_params(char *name, char *val); +int parse_gpio_operation(char *name); +int parse_gpio_param(const char *name, struct gpio_param_t *p_gpio_pin); +int wmt_graphic_init(void); +int uboot_vpp_alloc_framebuffer(unsigned int resx,unsigned int resy); +void lcd_blt_set_pwm(int no, int level, int freq); + +#ifdef CONFIG_VPP_SHENZHEN +int parse_backlight_params(void); +#endif + +#undef EXTERN + + +#endif /* __WM_LOGO_H__ */ |