123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- #include "drv_types.h"
- #include <linux/sched.h>
- #include <linux/workqueue.h>
- #include <drv_debug.h>
- #include "hdmi_processing.h"
- #include "hdmi_switch.h"
- #include "hdmi_hpd.h"
- #include "gpioi2c.h"
- #include "hdmi_time.h"
- #define bSwitchDBG ((*(UINT32*)DBGCONFIG2ADDR)&DBGCFG_CECSWITCH)
- #ifdef __KERNEL__
- #ifndef CONFIG_SUPPORT_DEBUG_MESSAGE
- #define switchdbg(fmt,args...)
- #else
- #define switchdbg(fmt,args...) printk(bSwitchDBG?("[HS] " fmt):"", ## args)
- #endif
- #endif
- static struct timer_list hpd_timer;
- static struct work_struct hpd_wq;
- static UINT8 it6633_readi2c(UINT8 addr)
- {
- UINT8 val = 0;
- hdmi_i2c_read(addr, &val, 1);
- return val;
- }
- static void it6633_writei2c(UINT8 addr, UINT8 val)
- {
- hdmi_i2c_write(addr, &val, 1);
- }
- static void hpd_timer_schedule(struct timer_list *, UINT32);
- static BOOL bToggle = false;
- static BOOL bSignalCheck = false;
- static UINT32 hpd_status = 0;
- static UINT8 sw_port = 0xff;
- static void apply_switch_hpd(UINT32 hpd)
- {
- UINT8 byte;
- byte = it6633_readi2c(0x29);
- byte &= 0xc1;
- byte |= ((hpd & 0x1) << 3);
- byte |= ((hpd & 0x2) << 1);
- byte |= ((hpd & 0x4) >> 1);
- switchdbg("%s byte 0x%02x\n", __FUNCTION__, byte);
- it6633_writei2c(0x29, byte);
- }
- static void toggle_hpd(UINT8 port)
- {
- UINT8 byte;
- switchdbg("%s port %s\n", __FUNCTION__,
- port == 0 ? "A" :
- port == 1 ? "B" :
- port == 2 ? "C" : "X"
- );
- byte = it6633_readi2c(0x29);
- byte &= (~(1 << (3 - (unsigned char)port)));
- it6633_writei2c(0x29, byte);
- it6633_writei2c(0x04, 0x00);
- byte = it6633_readi2c(0x29);
- byte &= 0xcf;
- byte |= 0x20;
- it6633_writei2c(0x29, byte);
- switchdbg("delay 500 ms\n");
- HDMI_DelayMs(500);
- byte &= 0xcf;
- it6633_writei2c(0x29, byte);
- byte = 0xB0 | ((unsigned char)port << 2) | (unsigned char)port;
- it6633_writei2c(0x06, byte);
- }
- static void check_hpd(void *dummy)
- {
- UINT8 diff_hpd_status = 0;
- UINT8 local_hpd_status = 0;
- local_hpd_status = it6633_readi2c(0x24) & 0x7;
- diff_hpd_status = local_hpd_status ^ hpd_status;
- hpd_status = local_hpd_status;
- if (bToggle || diff_hpd_status)
- {
- apply_switch_hpd(hpd_status);
- switchdbg("sw_port 0x%02x diff_hpd_status 0x%02x\n",
- sw_port, diff_hpd_status);
- if (sw_port != 0xff &&
- (diff_hpd_status & hpd_status & (1 << sw_port)))
- {
- switchdbg("delay 20 ms\n");
- HDMI_DelayMs(20);
- bToggle = true;
- }
- else
- {
- hdmi_hpd_update();
- }
- }
- if (bToggle && sw_port != 0xff)
- {
- toggle_hpd(sw_port);
- bToggle = false;
- hdmi_hpd_update();
- }
- if (bSignalCheck)
- {
- bSignalCheck = false;
- hdmi_signal_check_start();
- }
- }
- static void HPD_TIMER(void* dummy)
- {
- /* Schedule working queue to check hpd now */
- schedule_work(&hpd_wq);
- /* Check hpd periodically */
- hpd_timer_schedule(&hpd_timer, 50);
- }
- static void hpd_timer_schedule(struct timer_list *timer, UINT32 ten_ms)
- {
- del_timer(timer);
- timer->expires = jiffies + (HZ / 100) * ten_ms; // 10ms per unit
- timer->data = (UINT32)NULL;
- timer->function = (void (*)(ULONG))HPD_TIMER;
- add_timer(timer);
- }
- UINT32 hdmi_switch_hpd_status(void)
- {
- /* Return switch hpd status */
- // bit[0] - A port
- // bit[1] - B port
- // bit[2] - C port
- return hpd_status;
- }
- void hdmi_switch_disable(void)
- {
- switchdbg("%s\n", __FUNCTION__);
- it6633_writei2c(0x04, 0x08);
- }
- void hdmi_switch_enable(INT8 port)
- {
- switchdbg("%s port %s\n", __FUNCTION__,
- port == 0 ? "A" :
- port == 1 ? "B" :
- port == 2 ? "C" : "unknown");
- if (port < 0)
- {
- sw_port = 0xff;
- return;
- }
- port &= 0x3;
- sw_port = (unsigned char)port;
- bToggle = true;
- bSignalCheck = true;
- hpd_timer_schedule(&hpd_timer, 0);
- }
- void hdmi_switch_init(void)
- {
- switchdbg("%s\n", __FUNCTION__);
- /* Setup i2c mode, device id, and address length */
- hdmi_i2c_setup(USE_HW_I2C_SLAVE, 0x94, 1);
- it6633_writei2c(0x04, 0x08);
- /* Init DDC 5V status */
- hpd_status = 0;
- bToggle = false;
- /* Schedule timer to check hpd periodically */
- INIT_WORK(&hpd_wq, (work_func_t)check_hpd);
- init_timer(&hpd_timer);
- /* Schedule the 2 seconds timer,
- it will be rescheduled when current
- hdmi switch source is selected */
- hpd_timer_schedule(&hpd_timer, 200);
- /* Notice hdmi driver the current hpd status */
- }
- void hdmi_switch_power(BOOL bPwr)
- {
- switchdbg("%s(%s)\n", __FUNCTION__, bPwr ? "on" : "off");
- }
|