diff options
Diffstat (limited to 'drivers/staging/msm/mddihosti.c')
-rw-r--r-- | drivers/staging/msm/mddihosti.c | 2239 |
1 files changed, 0 insertions, 2239 deletions
diff --git a/drivers/staging/msm/mddihosti.c b/drivers/staging/msm/mddihosti.c deleted file mode 100644 index f9d6e91e8d5d..000000000000 --- a/drivers/staging/msm/mddihosti.c +++ /dev/null @@ -1,2239 +0,0 @@ -/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/mm.h> -#include <linux/fb.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/device.h> -#include <linux/dma-mapping.h> - -#include "msm_fb_panel.h" -#include "mddihost.h" -#include "mddihosti.h" - -#define FEATURE_MDDI_UNDERRUN_RECOVERY -#ifndef FEATURE_MDDI_DISABLE_REVERSE -static void mddi_read_rev_packet(byte *data_ptr); -#endif - -struct timer_list mddi_host_timer; - -#define MDDI_DEFAULT_TIMER_LENGTH 5000 /* 5 seconds */ -uint32 mddi_rtd_frequency = 60000; /* send RTD every 60 seconds */ -uint32 mddi_client_status_frequency = 60000; /* get status pkt every 60 secs */ - -boolean mddi_vsync_detect_enabled = FALSE; -mddi_gpio_info_type mddi_gpio; - -uint32 mddi_host_core_version; -boolean mddi_debug_log_statistics = FALSE; -/* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */ -/* default to TRUE in case MDP does not vote */ -static boolean mddi_host_mdp_active_flag = TRUE; -static uint32 mddi_log_stats_counter; -uint32 mddi_log_stats_frequency = 4000; - -#define MDDI_DEFAULT_REV_PKT_SIZE 0x20 - -#ifndef FEATURE_MDDI_DISABLE_REVERSE -static boolean mddi_rev_ptr_workaround = TRUE; -static uint32 mddi_reg_read_retry; -static uint32 mddi_reg_read_retry_max = 20; -static boolean mddi_enable_reg_read_retry = TRUE; -static boolean mddi_enable_reg_read_retry_once = FALSE; - -#define MDDI_MAX_REV_PKT_SIZE 0x60 - -#define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE 0x60 - -#define MDDI_VIDEO_REV_PKT_SIZE 0x40 -#define MDDI_REV_BUFFER_SIZE MDDI_MAX_REV_PKT_SIZE -static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE]; -#endif /* FEATURE_MDDI_DISABLE_REVERSE */ -/* leave these variables so graphics will compile */ - -#define MDDI_MAX_REV_DATA_SIZE 128 -/*lint -d__align(x) */ -boolean mddi_debug_clear_rev_data = TRUE; - -uint32 *mddi_reg_read_value_ptr; - -mddi_client_capability_type mddi_client_capability_pkt; -static boolean mddi_client_capability_request = FALSE; - -#ifndef FEATURE_MDDI_DISABLE_REVERSE - -#define MAX_MDDI_REV_HANDLERS 2 -#define INVALID_PKT_TYPE 0xFFFF - -typedef struct { - mddi_rev_handler_type handler; /* ISR to be executed */ - uint16 pkt_type; -} mddi_rev_pkt_handler_type; -static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] = - { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} }; - -static boolean mddi_rev_encap_user_request = FALSE; -static mddi_linked_list_notify_type mddi_rev_user; - -spinlock_t mddi_host_spin_lock; -extern uint32 mdp_in_processing; -#endif - -typedef enum { - MDDI_REV_IDLE -#ifndef FEATURE_MDDI_DISABLE_REVERSE - , MDDI_REV_REG_READ_ISSUED, - MDDI_REV_REG_READ_SENT, - MDDI_REV_ENCAP_ISSUED, - MDDI_REV_STATUS_REQ_ISSUED, - MDDI_REV_CLIENT_CAP_ISSUED -#endif -} mddi_rev_link_state_type; - -typedef enum { - MDDI_LINK_DISABLED, - MDDI_LINK_HIBERNATING, - MDDI_LINK_ACTIVATING, - MDDI_LINK_ACTIVE -} mddi_host_link_state_type; - -typedef struct { - uint32 count; - uint32 in_count; - uint32 disp_req_count; - uint32 state_change_count; - uint32 ll_done_count; - uint32 rev_avail_count; - uint32 error_count; - uint32 rev_encap_count; - uint32 llist_ptr_write_1; - uint32 llist_ptr_write_2; -} mddi_host_int_type; - -typedef struct { - uint32 fwd_crc_count; - uint32 rev_crc_count; - uint32 pri_underflow; - uint32 sec_underflow; - uint32 rev_overflow; - uint32 pri_overwrite; - uint32 sec_overwrite; - uint32 rev_overwrite; - uint32 dma_failure; - uint32 rtd_failure; - uint32 reg_read_failure; -#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY - uint32 pri_underrun_detected; -#endif -} mddi_host_stat_type; - -typedef struct { - uint32 rtd_cnt; - uint32 rev_enc_cnt; - uint32 vid_cnt; - uint32 reg_acc_cnt; - uint32 cli_stat_cnt; - uint32 cli_cap_cnt; - uint32 reg_read_cnt; - uint32 link_active_cnt; - uint32 link_hibernate_cnt; - uint32 vsync_response_cnt; - uint32 fwd_crc_cnt; - uint32 rev_crc_cnt; -} mddi_log_params_struct_type; - -typedef struct { - uint32 rtd_value; - uint32 rtd_counter; - uint32 client_status_cnt; - boolean rev_ptr_written; - uint8 *rev_ptr_start; - uint8 *rev_ptr_curr; - uint32 mddi_rev_ptr_write_val; - dma_addr_t rev_data_dma_addr; - uint16 rev_pkt_size; - mddi_rev_link_state_type rev_state; - mddi_host_link_state_type link_state; - mddi_host_driver_state_type driver_state; - boolean disable_hibernation; - uint32 saved_int_reg; - uint32 saved_int_en; - mddi_linked_list_type *llist_ptr; - dma_addr_t llist_dma_addr; - mddi_linked_list_type *llist_dma_ptr; - uint32 *rev_data_buf; - struct completion mddi_llist_avail_comp; - boolean mddi_waiting_for_llist_avail; - mddi_host_int_type int_type; - mddi_host_stat_type stats; - mddi_log_params_struct_type log_parms; - mddi_llist_info_type llist_info; - mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS]; -} mddi_host_cntl_type; - -static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM; -static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES]; -mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES]; -mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES]; -mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES]; -static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES]; - -extern uint32 mdp_total_vdopkts; - -static boolean mddi_host_io_clock_on = FALSE; -static boolean mddi_host_hclk_on = FALSE; - -int int_mddi_pri_flag = FALSE; -int int_mddi_ext_flag = FALSE; - -static void mddi_report_errors(uint32 int_reg) -{ - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if (int_reg & MDDI_INT_PRI_UNDERFLOW) { - pmhctl->stats.pri_underflow++; - MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n"); - } - if (int_reg & MDDI_INT_SEC_UNDERFLOW) { - pmhctl->stats.sec_underflow++; - MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n"); - } -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (int_reg & MDDI_INT_REV_OVERFLOW) { - pmhctl->stats.rev_overflow++; - MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n"); - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; - mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val); - - } - if (int_reg & MDDI_INT_CRC_ERROR) - MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n"); -#endif - if (int_reg & MDDI_INT_PRI_OVERWRITE) { - pmhctl->stats.pri_overwrite++; - MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n"); - } - if (int_reg & MDDI_INT_SEC_OVERWRITE) { - pmhctl->stats.sec_overwrite++; - MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n"); - } -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (int_reg & MDDI_INT_REV_OVERWRITE) { - pmhctl->stats.rev_overwrite++; - /* This will show up normally and is not a problem */ - MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n"); - } - if (int_reg & MDDI_INT_RTD_FAILURE) { - mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0); - pmhctl->stats.rtd_failure++; - MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n"); - } -#endif - if (int_reg & MDDI_INT_DMA_FAILURE) { - pmhctl->stats.dma_failure++; - MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n"); - } -} - -static void mddi_host_enable_io_clock(void) -{ - if (!MDDI_HOST_IS_IO_CLOCK_ON) - MDDI_HOST_ENABLE_IO_CLOCK; -} - -static void mddi_host_enable_hclk(void) -{ - - if (!MDDI_HOST_IS_HCLK_ON) - MDDI_HOST_ENABLE_HCLK; -} - -static void mddi_host_disable_io_clock(void) -{ -#ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE - if (MDDI_HOST_IS_IO_CLOCK_ON) - MDDI_HOST_DISABLE_IO_CLOCK; -#endif -} - -static void mddi_host_disable_hclk(void) -{ -#ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE - if (MDDI_HOST_IS_HCLK_ON) - MDDI_HOST_DISABLE_HCLK; -#endif -} - -static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep) -{ - uint16 vote_mask; - - if (host_idx == MDDI_HOST_PRIM) - vote_mask = 0x01; - else - vote_mask = 0x02; -} - -static void mddi_report_state_change(uint32 int_reg) -{ - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) && - (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) { - /* recover from condition where the io_clock was turned off by the - clock driver during a transition to hibernation. The io_clock - disable is to prevent MDP/MDDI underruns when changing ARM - clock speeds. In the process of halting the ARM, the hclk - divider needs to be set to 1. When it is set to 1, there is - a small time (usecs) when hclk is off or slow, and this can - cause an underrun. To prevent the underrun, clock driver turns - off the MDDI io_clock before making the change. */ - mddi_host_reg_out(CMD, MDDI_CMD_POWERUP); - } - - if (int_reg & MDDI_INT_LINK_ACTIVE) { - pmhctl->link_state = MDDI_LINK_ACTIVE; - pmhctl->log_parms.link_active_cnt++; - pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL); - MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n", - pmhctl->rtd_value); - /* now interrupt on hibernation */ - mddi_host_reg_outm(INTEN, - (MDDI_INT_IN_HIBERNATION | - MDDI_INT_LINK_ACTIVE), - MDDI_INT_IN_HIBERNATION); - -#ifdef DEBUG_MDDIHOSTI - /* if gpio interrupt is enabled, start polling at fastest - * registered rate - */ - if (mddi_gpio.polling_enabled) { - timer_reg(&mddi_gpio_poll_timer, - mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0); - } -#endif -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (mddi_rev_ptr_workaround) { - /* HW CR: need to reset reverse register stuff */ - pmhctl->rev_ptr_written = FALSE; - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; - } -#endif - /* vote on sleep */ - mddi_vote_to_sleep(host_idx, FALSE); - - if (host_idx == MDDI_HOST_PRIM) { - if (mddi_vsync_detect_enabled) { - /* - * Indicate to client specific code that vsync - * was enabled, but we did not detect a client - * intiated wakeup. The client specific - * handler can either reassert vsync detection, - * or treat this as a valid vsync. - */ - mddi_client_lcd_vsync_detected(FALSE); - pmhctl->log_parms.vsync_response_cnt++; - } - } - } - if (int_reg & MDDI_INT_IN_HIBERNATION) { - pmhctl->link_state = MDDI_LINK_HIBERNATING; - pmhctl->log_parms.link_hibernate_cnt++; - MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n"); - /* now interrupt on link_active */ -#ifdef FEATURE_MDDI_DISABLE_REVERSE - mddi_host_reg_outm(INTEN, - (MDDI_INT_MDDI_IN | - MDDI_INT_IN_HIBERNATION | - MDDI_INT_LINK_ACTIVE), - MDDI_INT_LINK_ACTIVE); -#else - mddi_host_reg_outm(INTEN, - (MDDI_INT_MDDI_IN | - MDDI_INT_IN_HIBERNATION | - MDDI_INT_LINK_ACTIVE), - (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE)); - - pmhctl->rtd_counter = mddi_rtd_frequency; - - if (pmhctl->rev_state != MDDI_REV_IDLE) { - /* a rev_encap will not wake up the link, so we do that here */ - pmhctl->link_state = MDDI_LINK_ACTIVATING; - mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); - } -#endif - - if (pmhctl->disable_hibernation) { - mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); - mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); - pmhctl->link_state = MDDI_LINK_ACTIVATING; - } -#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY - if ((pmhctl->llist_info.transmitting_start_idx != - UNASSIGNED_INDEX) - && - ((pmhctl-> - saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE | - MDDI_INT_PRI_PTR_READ)) == - MDDI_INT_PRI_PTR_READ)) { - mddi_linked_list_type *llist_dma; - llist_dma = pmhctl->llist_dma_ptr; - /* - * All indications are that we have not received a - * linked list done interrupt, due to an underrun - * condition. Recovery attempt is to send again. - */ - dma_coherent_pre_ops(); - /* Write to primary pointer register again */ - mddi_host_reg_out(PRI_PTR, - &llist_dma[pmhctl->llist_info. - transmitting_start_idx]); - pmhctl->stats.pri_underrun_detected++; - } -#endif - - /* vote on sleep */ - if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { - mddi_vote_to_sleep(host_idx, TRUE); - } - -#ifdef DEBUG_MDDIHOSTI - /* need to stop polling timer */ - if (mddi_gpio.polling_enabled) { - (void) timer_clr(&mddi_gpio_poll_timer, T_NONE); - } -#endif - } -} - -void mddi_host_timer_service(unsigned long data) -{ -#ifndef FEATURE_MDDI_DISABLE_REVERSE - unsigned long flags; -#endif - mddi_host_type host_idx; - mddi_host_cntl_type *pmhctl; - - unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH; - init_timer(&mddi_host_timer); - mddi_host_timer.function = mddi_host_timer_service; - mddi_host_timer.data = 0; - - mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000); - add_timer(&mddi_host_timer); - - for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES; - host_idx++) { - pmhctl = &(mhctl[host_idx]); - mddi_log_stats_counter += (uint32) time_ms; -#ifndef FEATURE_MDDI_DISABLE_REVERSE - pmhctl->rtd_counter += (uint32) time_ms; - pmhctl->client_status_cnt += (uint32) time_ms; - - if (host_idx == MDDI_HOST_PRIM) { - if (pmhctl->client_status_cnt >= - mddi_client_status_frequency) { - if ((pmhctl->link_state == - MDDI_LINK_HIBERNATING) - && (pmhctl->client_status_cnt > - mddi_client_status_frequency)) { - /* - * special case where we are hibernating - * and mddi_host_isr is not firing, so - * kick the link so that the status can - * be retrieved - */ - - /* need to wake up link before issuing - * rev encap command - */ - MDDI_MSG_INFO("wake up link!\n"); - spin_lock_irqsave(&mddi_host_spin_lock, - flags); - mddi_host_enable_hclk(); - mddi_host_enable_io_clock(); - pmhctl->link_state = - MDDI_LINK_ACTIVATING; - mddi_host_reg_out(CMD, - MDDI_CMD_LINK_ACTIVE); - spin_unlock_irqrestore - (&mddi_host_spin_lock, flags); - } else - if ((pmhctl->link_state == MDDI_LINK_ACTIVE) - && pmhctl->disable_hibernation) { - /* - * special case where we have disabled - * hibernation and mddi_host_isr - * is not firing, so enable interrupt - * for no pkts pending, which will - * generate an interrupt - */ - MDDI_MSG_INFO("kick isr!\n"); - spin_lock_irqsave(&mddi_host_spin_lock, - flags); - mddi_host_enable_hclk(); - mddi_host_reg_outm(INTEN, - MDDI_INT_NO_CMD_PKTS_PEND, - MDDI_INT_NO_CMD_PKTS_PEND); - spin_unlock_irqrestore - (&mddi_host_spin_lock, flags); - } - } - } -#endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */ - } - - /* Check if logging is turned on */ - for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES; - host_idx++) { - mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]); - pmhctl = &(mhctl[host_idx]); - - if (mddi_debug_log_statistics) { - - /* get video pkt count from MDP, since MDDI sw cannot know this */ - pmhctl->log_parms.vid_cnt = mdp_total_vdopkts; - - if (mddi_log_stats_counter >= mddi_log_stats_frequency) { - /* mddi_log_stats_counter = 0; */ - if (mddi_debug_log_statistics) { - MDDI_MSG_NOTICE - ("MDDI Statistics since last report:\n"); - MDDI_MSG_NOTICE(" Packets sent:\n"); - MDDI_MSG_NOTICE - (" %d RTD packet(s)\n", - pmhctl->log_parms.rtd_cnt - - prev_ptr->rtd_cnt); - if (prev_ptr->rtd_cnt != - pmhctl->log_parms.rtd_cnt) { - unsigned long flags; - spin_lock_irqsave - (&mddi_host_spin_lock, - flags); - mddi_host_enable_hclk(); - pmhctl->rtd_value = - mddi_host_reg_in(RTD_VAL); - spin_unlock_irqrestore - (&mddi_host_spin_lock, - flags); - MDDI_MSG_NOTICE - (" RTD value=%d\n", - pmhctl->rtd_value); - } - MDDI_MSG_NOTICE - (" %d VIDEO packets\n", - pmhctl->log_parms.vid_cnt - - prev_ptr->vid_cnt); - MDDI_MSG_NOTICE - (" %d Register Access packets\n", - pmhctl->log_parms.reg_acc_cnt - - prev_ptr->reg_acc_cnt); - MDDI_MSG_NOTICE - (" %d Reverse Encapsulation packet(s)\n", - pmhctl->log_parms.rev_enc_cnt - - prev_ptr->rev_enc_cnt); - if (prev_ptr->rev_enc_cnt != - pmhctl->log_parms.rev_enc_cnt) { - /* report # of reverse CRC errors */ - MDDI_MSG_NOTICE - (" %d reverse CRC errors detected\n", - pmhctl->log_parms. - rev_crc_cnt - - prev_ptr->rev_crc_cnt); - } - MDDI_MSG_NOTICE - (" Packets received:\n"); - MDDI_MSG_NOTICE - (" %d Client Status packets", - pmhctl->log_parms.cli_stat_cnt - - prev_ptr->cli_stat_cnt); - if (prev_ptr->cli_stat_cnt != - pmhctl->log_parms.cli_stat_cnt) { - MDDI_MSG_NOTICE - (" %d forward CRC errors reported\n", - pmhctl->log_parms. - fwd_crc_cnt - - prev_ptr->fwd_crc_cnt); - } - MDDI_MSG_NOTICE - (" %d Register Access Read packets\n", - pmhctl->log_parms.reg_read_cnt - - prev_ptr->reg_read_cnt); - - if (pmhctl->link_state == - MDDI_LINK_ACTIVE) { - MDDI_MSG_NOTICE - (" Current Link Status: Active\n"); - } else - if ((pmhctl->link_state == - MDDI_LINK_HIBERNATING) - || (pmhctl->link_state == - MDDI_LINK_ACTIVATING)) { - MDDI_MSG_NOTICE - (" Current Link Status: Hibernation\n"); - } else { - MDDI_MSG_NOTICE - (" Current Link Status: Inactive\n"); - } - MDDI_MSG_NOTICE - (" Active state entered %d times\n", - pmhctl->log_parms.link_active_cnt - - prev_ptr->link_active_cnt); - MDDI_MSG_NOTICE - (" Hibernation state entered %d times\n", - pmhctl->log_parms. - link_hibernate_cnt - - prev_ptr->link_hibernate_cnt); - } - } - prev_parms[host_idx] = pmhctl->log_parms; - } - } - if (mddi_log_stats_counter >= mddi_log_stats_frequency) - mddi_log_stats_counter = 0; - - return; -} /* mddi_host_timer_cb */ - -static void mddi_process_link_list_done(void) -{ - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - /* normal forward linked list packet(s) were sent */ - if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) { - MDDI_MSG_ERR("**** getting LL done, but no list ****\n"); - } else { - uint16 idx; - -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) { - /* special case where a register read packet was sent */ - pmhctl->rev_state = MDDI_REV_REG_READ_SENT; - if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) { - MDDI_MSG_ERR - ("**** getting LL done, but no list ****\n"); - } - } -#endif - for (idx = pmhctl->llist_info.transmitting_start_idx;;) { - uint16 next_idx = pmhctl->llist_notify[idx].next_idx; - /* with reg read we don't release the waiting tcb until after - * the reverse encapsulation has completed. - */ - if (idx != pmhctl->llist_info.reg_read_idx) { - /* notify task that may be waiting on this completion */ - if (pmhctl->llist_notify[idx].waiting) { - complete(& - (pmhctl->llist_notify[idx]. - done_comp)); - } - if (pmhctl->llist_notify[idx].done_cb != NULL) { - (*(pmhctl->llist_notify[idx].done_cb)) - (); - } - - pmhctl->llist_notify[idx].in_use = FALSE; - pmhctl->llist_notify[idx].waiting = FALSE; - pmhctl->llist_notify[idx].done_cb = NULL; - if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) { - /* static LLIST items are configured only once */ - pmhctl->llist_notify[idx].next_idx = - UNASSIGNED_INDEX; - } - /* - * currently, all linked list packets are - * register access, so we can increment the - * counter for that packet type here. - */ - pmhctl->log_parms.reg_acc_cnt++; - } - if (idx == pmhctl->llist_info.transmitting_end_idx) - break; - idx = next_idx; - if (idx == UNASSIGNED_INDEX) - MDDI_MSG_CRIT("MDDI linked list corruption!\n"); - } - - pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX; - pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX; - - if (pmhctl->mddi_waiting_for_llist_avail) { - if (! - (pmhctl-> - llist_notify[pmhctl->llist_info.next_free_idx]. - in_use)) { - pmhctl->mddi_waiting_for_llist_avail = FALSE; - complete(&(pmhctl->mddi_llist_avail_comp)); - } - } - } - - /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */ - mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0); - -} - -static void mddi_queue_forward_linked_list(void) -{ - uint16 first_pkt_index; - mddi_linked_list_type *llist_dma; - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - llist_dma = pmhctl->llist_dma_ptr; - - first_pkt_index = UNASSIGNED_INDEX; - - if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) { -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (pmhctl->llist_info.reg_read_waiting) { - if (pmhctl->rev_state == MDDI_REV_IDLE) { - /* - * we have a register read to send and - * can send it now - */ - pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED; - mddi_reg_read_retry = 0; - first_pkt_index = - pmhctl->llist_info.waiting_start_idx; - pmhctl->llist_info.reg_read_waiting = FALSE; - } - } else -#endif - { - /* - * not register read to worry about, go ahead and write - * anything that may be on the waiting list. - */ - first_pkt_index = pmhctl->llist_info.waiting_start_idx; - } - } - - if (first_pkt_index != UNASSIGNED_INDEX) { - pmhctl->llist_info.transmitting_start_idx = - pmhctl->llist_info.waiting_start_idx; - pmhctl->llist_info.transmitting_end_idx = - pmhctl->llist_info.waiting_end_idx; - pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX; - pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX; - - /* write to the primary pointer register */ - MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n", - first_pkt_index); - - pmhctl->int_type.llist_ptr_write_2++; - - dma_coherent_pre_ops(); - mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]); - - /* enable interrupt when complete */ - mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, - MDDI_INT_PRI_LINK_LIST_DONE); - - } - -} - -#ifndef FEATURE_MDDI_DISABLE_REVERSE -static void mddi_read_rev_packet(byte *data_ptr) -{ - uint16 i, length; - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - uint8 *rev_ptr_overflow = - (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE); - - /* first determine the length and handle invalid lengths */ - length = *pmhctl->rev_ptr_curr++; - if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; - length |= ((*pmhctl->rev_ptr_curr++) << 8); - if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; - if (length > (pmhctl->rev_pkt_size - 2)) { - MDDI_MSG_ERR("Invalid rev pkt length %d\n", length); - /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */ - length = pmhctl->rev_pkt_size - 2; - } - - /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr. - * Loop around if necessary. Don't bother reading the data. - */ - if (data_ptr == NULL) { - pmhctl->rev_ptr_curr += length; - if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) - pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE; - return; - } - - data_ptr[0] = length & 0x0ff; - data_ptr[1] = length >> 8; - data_ptr += 2; - /* copy the data to data_ptr byte-at-a-time */ - for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); - i++) - *data_ptr++ = *pmhctl->rev_ptr_curr++; - if (pmhctl->rev_ptr_curr >= rev_ptr_overflow) - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; - for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++) - *data_ptr++ = *pmhctl->rev_ptr_curr++; -} - -static void mddi_process_rev_packets(void) -{ - uint32 rev_packet_count; - word i; - uint32 crc_errors; - boolean mddi_reg_read_successful = FALSE; - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - pmhctl->log_parms.rev_enc_cnt++; - if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) && - (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) && - (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) { - MDDI_MSG_ERR("Wrong state %d for reverse int\n", - pmhctl->rev_state); - } - /* Turn off MDDI_INT_REV_AVAIL interrupt */ - mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0); - - /* Clear rev data avail int */ - mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL); - - /* Get Number of packets */ - rev_packet_count = mddi_host_reg_in(REV_PKT_CNT); - -#ifndef T_MSM7500 - /* Clear out rev packet counter */ - mddi_host_reg_out(REV_PKT_CNT, 0x0000); -#endif - -#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) - if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) && - (rev_packet_count > 0) && - (mddi_host_core_version == 0x28 || - mddi_host_core_version == 0x30)) { - - uint32 int_reg; - uint32 max_count = 0; - - mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val); - int_reg = mddi_host_reg_in(INT); - while ((int_reg & 0x100000) == 0) { - udelay(3); - int_reg = mddi_host_reg_in(INT); - if (++max_count > 100) - break; - } - } -#endif - - /* Get CRC error count */ - crc_errors = mddi_host_reg_in(REV_CRC_ERR); - if (crc_errors != 0) { - pmhctl->log_parms.rev_crc_cnt += crc_errors; - pmhctl->stats.rev_crc_count += crc_errors; - MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n", - crc_errors); -#ifndef T_MSM7500 - /* Clear CRC error count */ - mddi_host_reg_out(REV_CRC_ERR, 0x0000); -#endif - /* also issue an RTD to attempt recovery */ - pmhctl->rtd_counter = mddi_rtd_frequency; - } - - pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL); - - MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n", - rev_packet_count, - pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start, - pmhctl->rtd_value); - - if (rev_packet_count >= 1) { - mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start, - MDDI_REV_BUFFER_SIZE); - } - /* order the reads */ - dma_coherent_post_ops(); - for (i = 0; i < rev_packet_count; i++) { - mddi_rev_packet_type *rev_pkt_ptr; - - mddi_read_rev_packet(rev_packet_data); - - rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data; - - if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) { - MDDI_MSG_ERR("!!!invalid packet size: %d\n", - rev_pkt_ptr->packet_length); - } - - MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n", - rev_pkt_ptr->packet_type, - rev_pkt_ptr->packet_length); - - /* Do whatever you want to do with the data based on the packet type */ - switch (rev_pkt_ptr->packet_type) { - case 66: /* Client Capability */ - { - mddi_client_capability_type - *client_capability_pkt_ptr; - - client_capability_pkt_ptr = - (mddi_client_capability_type *) - rev_packet_data; - MDDI_MSG_NOTICE - ("Client Capability: Week=%d, Year=%d\n", - client_capability_pkt_ptr-> - Week_of_Manufacture, - client_capability_pkt_ptr-> - Year_of_Manufacture); - memcpy((void *)&mddi_client_capability_pkt, - (void *)rev_packet_data, - sizeof(mddi_client_capability_type)); - pmhctl->log_parms.cli_cap_cnt++; - } - break; - - case 70: /* Display Status */ - { - mddi_client_status_type *client_status_pkt_ptr; - - client_status_pkt_ptr = - (mddi_client_status_type *) rev_packet_data; - if ((client_status_pkt_ptr->crc_error_count != - 0) - || (client_status_pkt_ptr-> - reverse_link_request != 0)) { - MDDI_MSG_ERR - ("Client Status: RevReq=%d, CrcErr=%d\n", - client_status_pkt_ptr-> - reverse_link_request, - client_status_pkt_ptr-> - crc_error_count); - } else { - MDDI_MSG_DEBUG - ("Client Status: RevReq=%d, CrcErr=%d\n", - client_status_pkt_ptr-> - reverse_link_request, - client_status_pkt_ptr-> - crc_error_count); - } - pmhctl->log_parms.fwd_crc_cnt += - client_status_pkt_ptr->crc_error_count; - pmhctl->stats.fwd_crc_count += - client_status_pkt_ptr->crc_error_count; - pmhctl->log_parms.cli_stat_cnt++; - } - break; - - case 146: /* register access packet */ - { - mddi_register_access_packet_type - * regacc_pkt_ptr; - - regacc_pkt_ptr = - (mddi_register_access_packet_type *) - rev_packet_data; - - MDDI_MSG_DEBUG - ("Reg Acc parse reg=0x%x, value=0x%x\n", - regacc_pkt_ptr->register_address, - regacc_pkt_ptr->register_data_list); - - /* Copy register value to location passed in */ - if (mddi_reg_read_value_ptr) { -#if defined(T_MSM6280) && !defined(T_MSM7200) - /* only least significant 16 bits are valid with 6280 */ - *mddi_reg_read_value_ptr = - regacc_pkt_ptr-> - register_data_list & 0x0000ffff; -#else - *mddi_reg_read_value_ptr = - regacc_pkt_ptr->register_data_list; -#endif - mddi_reg_read_successful = TRUE; - mddi_reg_read_value_ptr = NULL; - } - -#ifdef DEBUG_MDDIHOSTI - if ((mddi_gpio.polling_enabled) && - (regacc_pkt_ptr->register_address == - mddi_gpio.polling_reg)) { - /* - * ToDo: need to call Linux GPIO call - * here... - */ - mddi_client_lcd_gpio_poll( - regacc_pkt_ptr->register_data_list); - } -#endif - pmhctl->log_parms.reg_read_cnt++; - } - break; - - default: /* any other packet */ - { - uint16 hdlr; - - for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; - hdlr++) { - if (mddi_rev_pkt_handler[hdlr]. - pkt_type == - rev_pkt_ptr->packet_type) { - (* - (mddi_rev_pkt_handler[hdlr]. - handler)) (rev_pkt_ptr); - /* pmhctl->rev_state = MDDI_REV_IDLE; */ - break; - } - } - if (hdlr >= MAX_MDDI_REV_HANDLERS) - MDDI_MSG_ERR("MDDI unknown rev pkt\n"); - } - break; - } - } - if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >= - (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) { - pmhctl->rev_ptr_written = FALSE; - } - - if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) { - pmhctl->rev_state = MDDI_REV_IDLE; - if (mddi_rev_user.waiting) { - mddi_rev_user.waiting = FALSE; - complete(&(mddi_rev_user.done_comp)); - } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) { - MDDI_MSG_ERR - ("Reverse Encap state, but no reg read in progress\n"); - } else { - if ((!mddi_reg_read_successful) && - (mddi_reg_read_retry < mddi_reg_read_retry_max) && - (mddi_enable_reg_read_retry)) { - /* - * There is a race condition that can happen - * where the reverse encapsulation message is - * sent out by the MDDI host before the register - * read packet is sent. As a work-around for - * that problem we issue the reverse - * encapsulation one more time before giving up. - */ - if (mddi_enable_reg_read_retry_once) - mddi_reg_read_retry = - mddi_reg_read_retry_max; - pmhctl->rev_state = MDDI_REV_REG_READ_SENT; - pmhctl->stats.reg_read_failure++; - } else { - uint16 reg_read_idx = - pmhctl->llist_info.reg_read_idx; - - mddi_reg_read_retry = 0; - if (pmhctl->llist_notify[reg_read_idx].waiting) { - complete(& - (pmhctl-> - llist_notify[reg_read_idx]. - done_comp)); - } - pmhctl->llist_info.reg_read_idx = - UNASSIGNED_INDEX; - if (pmhctl->llist_notify[reg_read_idx]. - done_cb != NULL) { - (* - (pmhctl->llist_notify[reg_read_idx]. - done_cb)) (); - } - pmhctl->llist_notify[reg_read_idx].next_idx = - UNASSIGNED_INDEX; - pmhctl->llist_notify[reg_read_idx].in_use = - FALSE; - pmhctl->llist_notify[reg_read_idx].waiting = - FALSE; - pmhctl->llist_notify[reg_read_idx].done_cb = - NULL; - if (!mddi_reg_read_successful) - pmhctl->stats.reg_read_failure++; - } - } - } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) { -#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) - if (mddi_host_core_version == 0x28 || - mddi_host_core_version == 0x30) { - mddi_host_reg_out(FIFO_ALLOC, 0x00); - pmhctl->rev_ptr_written = TRUE; - mddi_host_reg_out(REV_PTR, - pmhctl->mddi_rev_ptr_write_val); - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; - mddi_host_reg_out(CMD, 0xC00); - } -#endif - - if (mddi_rev_user.waiting) { - mddi_rev_user.waiting = FALSE; - complete(&(mddi_rev_user.done_comp)); - } - pmhctl->rev_state = MDDI_REV_IDLE; - } else { - pmhctl->rev_state = MDDI_REV_IDLE; - } - - /* pmhctl->rev_state = MDDI_REV_IDLE; */ - - /* Re-enable interrupt */ - mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, - MDDI_INT_REV_DATA_AVAIL); - -} - -static void mddi_issue_reverse_encapsulation(void) -{ - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - /* Only issue a reverse encapsulation packet if: - * 1) another reverse is not in progress (MDDI_REV_IDLE). - * 2) a register read has been sent (MDDI_REV_REG_READ_SENT). - * 3) forward is not in progress, because of a hw bug in client that - * causes forward crc errors on packet immediately after rev encap. - */ - if (((pmhctl->rev_state == MDDI_REV_IDLE) || - (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) && - (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && - (!mdp_in_processing)) { - uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP; - - if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) || - (mddi_rev_encap_user_request == TRUE)) { - mddi_host_enable_io_clock(); - if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { - /* need to wake up link before issuing rev encap command */ - MDDI_MSG_DEBUG("wake up link!\n"); - pmhctl->link_state = MDDI_LINK_ACTIVATING; - mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); - } else { - if (pmhctl->rtd_counter >= mddi_rtd_frequency) { - MDDI_MSG_DEBUG - ("mddi sending RTD command!\n"); - mddi_host_reg_out(CMD, - MDDI_CMD_SEND_RTD); - pmhctl->rtd_counter = 0; - pmhctl->log_parms.rtd_cnt++; - } - if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) { - /* this is generic reverse request by user, so - * reset the waiting flag. */ - mddi_rev_encap_user_request = FALSE; - } - /* link is active so send reverse encap to get register read results */ - pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED; - mddi_command = MDDI_CMD_SEND_REV_ENCAP; - MDDI_MSG_DEBUG("sending rev encap!\n"); - } - } else - if ((pmhctl->client_status_cnt >= - mddi_client_status_frequency) - || mddi_client_capability_request) { - mddi_host_enable_io_clock(); - if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { - /* only wake up the link if it client status is overdue */ - if ((pmhctl->client_status_cnt >= - (mddi_client_status_frequency * 2)) - || mddi_client_capability_request) { - /* need to wake up link before issuing rev encap command */ - MDDI_MSG_DEBUG("wake up link!\n"); - pmhctl->link_state = - MDDI_LINK_ACTIVATING; - mddi_host_reg_out(CMD, - MDDI_CMD_LINK_ACTIVE); - } - } else { - if (pmhctl->rtd_counter >= mddi_rtd_frequency) { - MDDI_MSG_DEBUG - ("mddi sending RTD command!\n"); - mddi_host_reg_out(CMD, - MDDI_CMD_SEND_RTD); - pmhctl->rtd_counter = 0; - pmhctl->log_parms.rtd_cnt++; - } - /* periodically get client status */ - MDDI_MSG_DEBUG - ("mddi sending rev enc! (get status)\n"); - if (mddi_client_capability_request) { - pmhctl->rev_state = - MDDI_REV_CLIENT_CAP_ISSUED; - mddi_command = MDDI_CMD_GET_CLIENT_CAP; - mddi_client_capability_request = FALSE; - } else { - pmhctl->rev_state = - MDDI_REV_STATUS_REQ_ISSUED; - pmhctl->client_status_cnt = 0; - mddi_command = - MDDI_CMD_GET_CLIENT_STATUS; - } - } - } - if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) || - (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) || - (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) { - pmhctl->int_type.rev_encap_count++; -#if defined(T_MSM6280) && !defined(T_MSM7200) - mddi_rev_pointer_written = TRUE; - mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val); - mddi_rev_ptr_curr = mddi_rev_ptr_start; - /* force new rev ptr command */ - mddi_host_reg_out(CMD, 0xC00); -#else - if (!pmhctl->rev_ptr_written) { - MDDI_MSG_DEBUG("writing reverse pointer!\n"); - pmhctl->rev_ptr_written = TRUE; -#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) - if ((pmhctl->rev_state == - MDDI_REV_CLIENT_CAP_ISSUED) && - (mddi_host_core_version == 0x28 || - mddi_host_core_version == 0x30)) { - pmhctl->rev_ptr_written = FALSE; - mddi_host_reg_out(FIFO_ALLOC, 0x02); - } else - mddi_host_reg_out(REV_PTR, - pmhctl-> - mddi_rev_ptr_write_val); -#else - mddi_host_reg_out(REV_PTR, - pmhctl-> - mddi_rev_ptr_write_val); -#endif - } -#endif - if (mddi_debug_clear_rev_data) { - uint16 i; - for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++) - pmhctl->rev_data_buf[i] = 0xdddddddd; - /* clean cache */ - mddi_flush_cache_lines(pmhctl->rev_data_buf, - MDDI_MAX_REV_DATA_SIZE); - } - - /* send reverse encapsulation to get needed data */ - mddi_host_reg_out(CMD, mddi_command); - } - } - -} - -static void mddi_process_client_initiated_wakeup(void) -{ - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one - * time for each entry into hibernation */ - mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0); - - if (host_idx == MDDI_HOST_PRIM) { - if (mddi_vsync_detect_enabled) { - mddi_host_enable_io_clock(); -#ifndef MDDI_HOST_DISP_LISTEN - /* issue command to bring up link */ - /* need to do this to clear the vsync condition */ - if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { - pmhctl->link_state = MDDI_LINK_ACTIVATING; - mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); - } -#endif - /* - * Indicate to client specific code that vsync was - * enabled, and we did not detect a client initiated - * wakeup. The client specific handler can clear the - * condition if necessary to prevent subsequent - * client initiated wakeups. - */ - mddi_client_lcd_vsync_detected(TRUE); - pmhctl->log_parms.vsync_response_cnt++; - MDDI_MSG_NOTICE("MDDI_INT_IN condition\n"); - - } - } - - if (mddi_gpio.polling_enabled) { - mddi_host_enable_io_clock(); - /* check interrupt status now */ - (void)mddi_queue_register_read_int(mddi_gpio.polling_reg, - &mddi_gpio.polling_val); - } -} -#endif /* FEATURE_MDDI_DISABLE_REVERSE */ - -static void mddi_host_isr(void) -{ - uint32 int_reg, int_en; -#ifndef FEATURE_MDDI_DISABLE_REVERSE - uint32 status_reg; -#endif - mddi_host_type host_idx = mddi_curr_host; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if (!MDDI_HOST_IS_HCLK_ON) { - MDDI_HOST_ENABLE_HCLK; - MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n"); - } - int_reg = mddi_host_reg_in(INT); - int_en = mddi_host_reg_in(INTEN); - pmhctl->saved_int_reg = int_reg; - pmhctl->saved_int_en = int_en; - int_reg = int_reg & int_en; - pmhctl->int_type.count++; - - -#ifndef FEATURE_MDDI_DISABLE_REVERSE - status_reg = mddi_host_reg_in(STAT); - - if ((int_reg & MDDI_INT_MDDI_IN) || - ((int_en & MDDI_INT_MDDI_IN) && - ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) { - /* - * The MDDI_IN condition will clear itself, and so it is - * possible that MDDI_IN was the reason for the isr firing, - * even though the interrupt register does not have the - * MDDI_IN bit set. To check if this was the case we need to - * look at the status register bit that signifies a client - * initiated wakeup. If the status register bit is set, as well - * as the MDDI_IN interrupt enabled, then we treat this as a - * client initiated wakeup. - */ - if (int_reg & MDDI_INT_MDDI_IN) - pmhctl->int_type.in_count++; - mddi_process_client_initiated_wakeup(); - } -#endif - - if (int_reg & MDDI_INT_LINK_STATE_CHANGES) { - pmhctl->int_type.state_change_count++; - mddi_report_state_change(int_reg); - } - - if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) { - pmhctl->int_type.ll_done_count++; - mddi_process_link_list_done(); - } -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (int_reg & MDDI_INT_REV_DATA_AVAIL) { - pmhctl->int_type.rev_avail_count++; - mddi_process_rev_packets(); - } -#endif - - if (int_reg & MDDI_INT_ERROR_CONDITIONS) { - pmhctl->int_type.error_count++; - mddi_report_errors(int_reg); - - mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS); - } -#ifndef FEATURE_MDDI_DISABLE_REVERSE - mddi_issue_reverse_encapsulation(); - - if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) && - (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED)) -#endif - /* don't want simultaneous reverse and forward with Eagle */ - mddi_queue_forward_linked_list(); - - if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) { - /* this interrupt is used to kick the isr when hibernation is disabled */ - mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0); - } - - if ((!mddi_host_mdp_active_flag) && - (!mddi_vsync_detect_enabled) && - (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && - (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) && - (pmhctl->rev_state == MDDI_REV_IDLE)) { - if (pmhctl->link_state == MDDI_LINK_HIBERNATING) { - mddi_host_disable_io_clock(); - mddi_host_disable_hclk(); - } -#ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION - else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) && - (!pmhctl->disable_hibernation)) { - mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN); - } -#endif - } -} - -static void mddi_host_isr_primary(void) -{ - mddi_curr_host = MDDI_HOST_PRIM; - mddi_host_isr(); -} - -irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr) -{ - mddi_host_isr_primary(); - return IRQ_HANDLED; -} - -static void mddi_host_isr_external(void) -{ - mddi_curr_host = MDDI_HOST_EXT; - mddi_host_isr(); - mddi_curr_host = MDDI_HOST_PRIM; -} - -irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr) -{ - mddi_host_isr_external(); - return IRQ_HANDLED; -} - -static void mddi_host_initialize_registers(mddi_host_type host_idx) -{ - uint32 pad_reg_val; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if (pmhctl->driver_state == MDDI_DRIVER_ENABLED) - return; - - /* turn on HCLK to MDDI host core */ - mddi_host_enable_hclk(); - - /* MDDI Reset command */ - mddi_host_reg_out(CMD, MDDI_CMD_RESET); - - /* Version register (= 0x01) */ - mddi_host_reg_out(VERSION, 0x0001); - - /* Bytes per subframe register */ - mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME); - - /* Subframes per media frames register (= 0x03) */ - mddi_host_reg_out(SPM, 0x0003); - - /* Turn Around 1 register (= 0x05) */ - mddi_host_reg_out(TA1_LEN, 0x0005); - - /* Turn Around 2 register (= 0x0C) */ - mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN); - - /* Drive hi register (= 0x96) */ - mddi_host_reg_out(DRIVE_HI, 0x0096); - - /* Drive lo register (= 0x32) */ - mddi_host_reg_out(DRIVE_LO, 0x0032); - - /* Display wakeup count register (= 0x3c) */ - mddi_host_reg_out(DISP_WAKE, 0x003c); - - /* Reverse Rate Divisor register (= 0x2) */ - mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV); - -#ifndef FEATURE_MDDI_DISABLE_REVERSE - /* Reverse Pointer Size */ - mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE); - - /* Rev Encap Size */ - mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); -#endif - - /* Periodic Rev Encap */ - /* don't send periodically */ - mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP); - - pad_reg_val = mddi_host_reg_in(PAD_CTL); - if (pad_reg_val == 0) { - /* If we are turning on band gap, need to wait 5us before turning - * on the rest of the PAD */ - mddi_host_reg_out(PAD_CTL, 0x08000); - udelay(5); - } -#ifdef T_MSM7200 - /* Recommendation from PAD hw team */ - mddi_host_reg_out(PAD_CTL, 0xa850a); -#else - /* Recommendation from PAD hw team */ - mddi_host_reg_out(PAD_CTL, 0xa850f); -#endif - -#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40) - mddi_host_reg_out(PAD_IO_CTL, 0x00320000); - mddi_host_reg_out(PAD_CAL, 0x00220020); -#endif - - mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff); - -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (mddi_host_core_version >= 8) - mddi_rev_ptr_workaround = FALSE; - pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start; -#endif - - if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19)) - mddi_host_reg_out(TEST, 0x2); - - /* Need an even number for counts */ - mddi_host_reg_out(DRIVER_START_CNT, 0x60006); - -#ifndef T_MSM7500 - /* Setup defaults for MDP related register */ - mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666); - mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3); - mddi_host_reg_out(MDP_VID_CLIENTID, 0); -#endif - - /* automatically hibernate after 1 empty subframe */ - if (pmhctl->disable_hibernation) - mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); - else - mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); - - /* Bring up link if display (client) requests it */ -#ifdef MDDI_HOST_DISP_LISTEN - mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN); -#else - mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE); -#endif - -} - -void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable) -{ - unsigned long flags; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - spin_lock_irqsave(&mddi_host_spin_lock, flags); - - /* turn on HCLK to MDDI host core if it has been disabled */ - mddi_host_enable_hclk(); - /* Clear MDDI Interrupt enable reg */ - mddi_host_reg_out(INTEN, 0); - - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - - if (enable) { - pmhctl->driver_state = MDDI_DRIVER_ENABLED; - - if (host_idx == MDDI_HOST_PRIM) { - if (request_irq - (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED, - "PMDH", 0) != 0) - printk(KERN_ERR - "a mddi: unable to request_irq\n"); - else - int_mddi_pri_flag = TRUE; - } else { - if (request_irq - (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED, - "EMDH", 0) != 0) - printk(KERN_ERR - "b mddi: unable to request_irq\n"); - else - int_mddi_ext_flag = TRUE; - } - - /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */ -#ifdef FEATURE_MDDI_DISABLE_REVERSE - mddi_host_reg_out(INTEN, - MDDI_INT_ERROR_CONDITIONS | - MDDI_INT_LINK_STATE_CHANGES); -#else - /* Reverse Pointer register */ - pmhctl->rev_ptr_written = FALSE; - - mddi_host_reg_out(INTEN, - MDDI_INT_REV_DATA_AVAIL | - MDDI_INT_ERROR_CONDITIONS | - MDDI_INT_LINK_STATE_CHANGES); - pmhctl->rtd_counter = mddi_rtd_frequency; - pmhctl->client_status_cnt = 0; -#endif - } else { - if (pmhctl->driver_state == MDDI_DRIVER_ENABLED) - pmhctl->driver_state = MDDI_DRIVER_DISABLED; - } - -} - -static void mddi_host_powerup(mddi_host_type host_idx) -{ - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if (pmhctl->link_state != MDDI_LINK_DISABLED) - return; - - /* enable IO_CLK and hclk to MDDI host core */ - mddi_host_enable_io_clock(); - - mddi_host_initialize_registers(host_idx); - mddi_host_configure_interrupts(host_idx, TRUE); - - pmhctl->link_state = MDDI_LINK_ACTIVATING; - - /* Link activate command */ - mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE); - -#ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ - MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n", - CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2); -#else - MDDI_MSG_NOTICE("MDDI Host: Activating Link\n"); -#endif - - /* Initialize the timer */ - if (host_idx == MDDI_HOST_PRIM) - mddi_host_timer_service(0); -} - -void mddi_host_init(mddi_host_type host_idx) -/* Write out the MDDI configuration registers */ -{ - static boolean initialized = FALSE; - mddi_host_cntl_type *pmhctl; - - if (host_idx >= MDDI_NUM_HOST_CORES) { - MDDI_MSG_ERR("Invalid host core index\n"); - return; - } - - if (!initialized) { - uint16 idx; - mddi_host_type host; - for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) { - pmhctl = &(mhctl[host]); - initialized = TRUE; - - pmhctl->llist_ptr = - dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE, - &(pmhctl->llist_dma_addr), - GFP_KERNEL); - pmhctl->llist_dma_ptr = - (mddi_linked_list_type *) (void *)pmhctl-> - llist_dma_addr; -#ifdef FEATURE_MDDI_DISABLE_REVERSE - pmhctl->rev_data_buf = NULL; - if (pmhctl->llist_ptr == NULL) -#else - mddi_rev_user.waiting = FALSE; - init_completion(&(mddi_rev_user.done_comp)); - pmhctl->rev_data_buf = - dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE, - &(pmhctl->rev_data_dma_addr), - GFP_KERNEL); - if ((pmhctl->llist_ptr == NULL) - || (pmhctl->rev_data_buf == NULL)) -#endif - { - MDDI_MSG_CRIT - ("unable to alloc non-cached memory\n"); - } - llist_extern[host] = pmhctl->llist_ptr; - llist_dma_extern[host] = pmhctl->llist_dma_ptr; - llist_extern_notify[host] = pmhctl->llist_notify; - - for (idx = 0; idx < UNASSIGNED_INDEX; idx++) { - init_completion(& - (pmhctl->llist_notify[idx]. - done_comp)); - } - init_completion(&(pmhctl->mddi_llist_avail_comp)); - spin_lock_init(&mddi_host_spin_lock); - pmhctl->mddi_waiting_for_llist_avail = FALSE; - pmhctl->mddi_rev_ptr_write_val = - (uint32) (void *)(pmhctl->rev_data_dma_addr); - pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf; - - pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE; - pmhctl->rev_state = MDDI_REV_IDLE; -#ifdef IMAGE_MODEM_PROC - /* assume hibernation state is last state from APPS proc, so that - * we don't reinitialize the host core */ - pmhctl->link_state = MDDI_LINK_HIBERNATING; -#else - pmhctl->link_state = MDDI_LINK_DISABLED; -#endif - pmhctl->driver_state = MDDI_DRIVER_DISABLED; - pmhctl->disable_hibernation = FALSE; - - /* initialize llist variables */ - pmhctl->llist_info.transmitting_start_idx = - UNASSIGNED_INDEX; - pmhctl->llist_info.transmitting_end_idx = - UNASSIGNED_INDEX; - pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX; - pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX; - pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX; - pmhctl->llist_info.next_free_idx = - MDDI_FIRST_DYNAMIC_LLIST_IDX; - pmhctl->llist_info.reg_read_waiting = FALSE; - - mddi_vsync_detect_enabled = FALSE; - mddi_gpio.polling_enabled = FALSE; - - pmhctl->int_type.count = 0; - pmhctl->int_type.in_count = 0; - pmhctl->int_type.disp_req_count = 0; - pmhctl->int_type.state_change_count = 0; - pmhctl->int_type.ll_done_count = 0; - pmhctl->int_type.rev_avail_count = 0; - pmhctl->int_type.error_count = 0; - pmhctl->int_type.rev_encap_count = 0; - pmhctl->int_type.llist_ptr_write_1 = 0; - pmhctl->int_type.llist_ptr_write_2 = 0; - - pmhctl->stats.fwd_crc_count = 0; - pmhctl->stats.rev_crc_count = 0; - pmhctl->stats.pri_underflow = 0; - pmhctl->stats.sec_underflow = 0; - pmhctl->stats.rev_overflow = 0; - pmhctl->stats.pri_overwrite = 0; - pmhctl->stats.sec_overwrite = 0; - pmhctl->stats.rev_overwrite = 0; - pmhctl->stats.dma_failure = 0; - pmhctl->stats.rtd_failure = 0; - pmhctl->stats.reg_read_failure = 0; -#ifdef FEATURE_MDDI_UNDERRUN_RECOVERY - pmhctl->stats.pri_underrun_detected = 0; -#endif - - pmhctl->log_parms.rtd_cnt = 0; - pmhctl->log_parms.rev_enc_cnt = 0; - pmhctl->log_parms.vid_cnt = 0; - pmhctl->log_parms.reg_acc_cnt = 0; - pmhctl->log_parms.cli_stat_cnt = 0; - pmhctl->log_parms.cli_cap_cnt = 0; - pmhctl->log_parms.reg_read_cnt = 0; - pmhctl->log_parms.link_active_cnt = 0; - pmhctl->log_parms.link_hibernate_cnt = 0; - pmhctl->log_parms.fwd_crc_cnt = 0; - pmhctl->log_parms.rev_crc_cnt = 0; - pmhctl->log_parms.vsync_response_cnt = 0; - - prev_parms[host_idx] = pmhctl->log_parms; - mddi_client_capability_pkt.packet_length = 0; - } - -#ifndef T_MSM7500 - /* tell clock driver we are user of this PLL */ - MDDI_HOST_ENABLE_IO_CLOCK; -#endif - } - - mddi_host_powerup(host_idx); - pmhctl = &(mhctl[host_idx]); -} - -#ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT -static uint32 mddi_client_id; - -uint32 mddi_get_client_id(void) -{ - -#ifndef FEATURE_MDDI_DISABLE_REVERSE - mddi_host_type host_idx = MDDI_HOST_PRIM; - static boolean client_detection_try = FALSE; - mddi_host_cntl_type *pmhctl; - unsigned long flags; - uint16 saved_rev_pkt_size; - - if (!client_detection_try) { - /* Toshiba display requires larger drive_lo value */ - mddi_host_reg_out(DRIVE_LO, 0x0050); - - pmhctl = &(mhctl[MDDI_HOST_PRIM]); - - saved_rev_pkt_size = pmhctl->rev_pkt_size; - - /* Increase Rev Encap Size */ - pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE; - mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); - - /* disable hibernation temporarily */ - if (!pmhctl->disable_hibernation) - mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE); - - mddi_rev_user.waiting = TRUE; - INIT_COMPLETION(mddi_rev_user.done_comp); - - spin_lock_irqsave(&mddi_host_spin_lock, flags); - - /* turn on clock(s), if they have been disabled */ - mddi_host_enable_hclk(); - mddi_host_enable_io_clock(); - - mddi_client_capability_request = TRUE; - - if (pmhctl->rev_state == MDDI_REV_IDLE) { - /* attempt to send the reverse encapsulation now */ - mddi_issue_reverse_encapsulation(); - } - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - - wait_for_completion_killable(&(mddi_rev_user.done_comp)); - - /* Set Rev Encap Size back to its original value */ - pmhctl->rev_pkt_size = saved_rev_pkt_size; - mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size); - - /* reenable auto-hibernate */ - if (!pmhctl->disable_hibernation) - mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); - - mddi_host_reg_out(DRIVE_LO, 0x0032); - client_detection_try = TRUE; - - mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) | - mddi_client_capability_pkt.Product_Code; - - if (!mddi_client_id) - mddi_disable(1); - } - -#if 0 - switch (mddi_client_capability_pkt.Mfr_Name) { - case 0x4474: - if ((mddi_client_capability_pkt.Product_Code != 0x8960) && - (target == DISPLAY_1)) { - ret = PRISM_WVGA; - } - break; - - case 0xD263: - if (target == DISPLAY_1) - ret = TOSHIBA_VGA_PRIM; - else if (target == DISPLAY_2) - ret = TOSHIBA_QCIF_SECD; - break; - - case 0: - if (mddi_client_capability_pkt.Product_Code == 0x8835) { - if (target == DISPLAY_1) - ret = SHARP_QVGA_PRIM; - else if (target == DISPLAY_2) - ret = SHARP_128x128_SECD; - } - break; - - default: - break; - } - - if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM) - && (ret != TOSHIBA_QCIF_SECD)) { - /* Not a Toshiba display, so change drive_lo back to default value */ - mddi_host_reg_out(DRIVE_LO, 0x0032); - } -#endif - -#endif - - return mddi_client_id; -} -#endif - -void mddi_host_powerdown(mddi_host_type host_idx) -{ - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if (host_idx >= MDDI_NUM_HOST_CORES) { - MDDI_MSG_ERR("Invalid host core index\n"); - return; - } - - if (pmhctl->driver_state == MDDI_DRIVER_RESET) { - return; - } - - if (host_idx == MDDI_HOST_PRIM) { - /* disable timer */ - del_timer(&mddi_host_timer); - } - - mddi_host_configure_interrupts(host_idx, FALSE); - - /* turn on HCLK to MDDI host core if it has been disabled */ - mddi_host_enable_hclk(); - - /* MDDI Reset command */ - mddi_host_reg_out(CMD, MDDI_CMD_RESET); - - /* Pad Control Register */ - mddi_host_reg_out(PAD_CTL, 0x0); - - /* disable IO_CLK and hclk to MDDI host core */ - mddi_host_disable_io_clock(); - mddi_host_disable_hclk(); - - pmhctl->link_state = MDDI_LINK_DISABLED; - pmhctl->driver_state = MDDI_DRIVER_RESET; - - MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n"); - -} - -uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait) -{ - unsigned long flags; - uint16 ret_idx; - boolean forced_wait = FALSE; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - ret_idx = pmhctl->llist_info.next_free_idx; - - pmhctl->llist_info.next_free_idx++; - if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS) - pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX; - spin_lock_irqsave(&mddi_host_spin_lock, flags); - if (pmhctl->llist_notify[ret_idx].in_use) { - if (!wait) { - pmhctl->llist_info.next_free_idx = ret_idx; - ret_idx = UNASSIGNED_INDEX; - } else { - forced_wait = TRUE; - INIT_COMPLETION(pmhctl->mddi_llist_avail_comp); - } - } - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - - if (forced_wait) { - wait_for_completion_killable(& - (pmhctl-> - mddi_llist_avail_comp)); - MDDI_MSG_ERR("task waiting on mddi llist item\n"); - } - - if (ret_idx != UNASSIGNED_INDEX) { - pmhctl->llist_notify[ret_idx].waiting = FALSE; - pmhctl->llist_notify[ret_idx].done_cb = NULL; - pmhctl->llist_notify[ret_idx].in_use = TRUE; - pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX; - } - - return ret_idx; -} - -uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait) -{ -#ifdef FEATURE_MDDI_DISABLE_REVERSE - MDDI_MSG_CRIT("No reverse link available\n"); - (void)wait; - return FALSE; -#else - unsigned long flags; - uint16 ret_idx; - boolean error = FALSE; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - spin_lock_irqsave(&mddi_host_spin_lock, flags); - if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) { - /* need to block here or is this an error condition? */ - error = TRUE; - ret_idx = UNASSIGNED_INDEX; - } - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - - if (!error) { - ret_idx = pmhctl->llist_info.reg_read_idx = - mddi_get_next_free_llist_item(host_idx, wait); - /* clear the reg_read_waiting flag */ - pmhctl->llist_info.reg_read_waiting = FALSE; - } - - if (error) - MDDI_MSG_ERR("***** Reg read still in progress! ****\n"); - return ret_idx; -#endif - -} - -void mddi_queue_forward_packets(uint16 first_llist_idx, - uint16 last_llist_idx, - boolean wait, - mddi_llist_done_cb_type llist_done_cb, - mddi_host_type host_idx) -{ - unsigned long flags; - mddi_linked_list_type *llist; - mddi_linked_list_type *llist_dma; - mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]); - - if ((first_llist_idx >= UNASSIGNED_INDEX) || - (last_llist_idx >= UNASSIGNED_INDEX)) { - MDDI_MSG_ERR("MDDI queueing invalid linked list\n"); - return; - } - - if (pmhctl->link_state == MDDI_LINK_DISABLED) - MDDI_MSG_CRIT("MDDI host powered down!\n"); - - llist = pmhctl->llist_ptr; - llist_dma = pmhctl->llist_dma_ptr; - - /* clean cache so MDDI host can read data */ - memory_barrier(); - - pmhctl->llist_notify[last_llist_idx].waiting = wait; - if (wait) - INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp); - pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb; - - spin_lock_irqsave(&mddi_host_spin_lock, flags); - - if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) && - (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) && - (pmhctl->rev_state == MDDI_REV_IDLE)) { - /* no packets are currently transmitting */ -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { - /* This is the special case where the packet is a register read. */ - pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED; - mddi_reg_read_retry = 0; - /* mddi_rev_reg_read_attempt = 1; */ - } -#endif - /* assign transmitting index values */ - pmhctl->llist_info.transmitting_start_idx = first_llist_idx; - pmhctl->llist_info.transmitting_end_idx = last_llist_idx; - - /* turn on clock(s), if they have been disabled */ - mddi_host_enable_hclk(); - mddi_host_enable_io_clock(); - pmhctl->int_type.llist_ptr_write_1++; - /* Write to primary pointer register */ - dma_coherent_pre_ops(); - mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]); - - /* enable interrupt when complete */ - mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, - MDDI_INT_PRI_LINK_LIST_DONE); - - } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) { -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { - /* - * we have a register read to send but need to wait - * for current reverse activity to end or there are - * packets currently transmitting - */ - /* mddi_rev_reg_read_attempt = 0; */ - pmhctl->llist_info.reg_read_waiting = TRUE; - } -#endif - - /* assign waiting index values */ - pmhctl->llist_info.waiting_start_idx = first_llist_idx; - pmhctl->llist_info.waiting_end_idx = last_llist_idx; - } else { - uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx; -#ifndef FEATURE_MDDI_DISABLE_REVERSE - if (first_llist_idx == pmhctl->llist_info.reg_read_idx) { - /* - * we have a register read to send but need to wait - * for current reverse activity to end or there are - * packets currently transmitting - */ - /* mddi_rev_reg_read_attempt = 0; */ - pmhctl->llist_info.reg_read_waiting = TRUE; - } -#endif - - llist = pmhctl->llist_ptr; - - /* clear end flag in previous last packet */ - llist[prev_end_idx].link_controller_flags = 0; - pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx; - - /* set the next_packet_pointer of the previous last packet */ - llist[prev_end_idx].next_packet_pointer = - (void *)(&llist_dma[first_llist_idx]); - - /* clean cache so MDDI host can read data */ - memory_barrier(); - - /* assign new waiting last index value */ - pmhctl->llist_info.waiting_end_idx = last_llist_idx; - } - - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - -} - -void mddi_host_write_pix_attr_reg(uint32 value) -{ - (void)value; -} - -void mddi_queue_reverse_encapsulation(boolean wait) -{ -#ifdef FEATURE_MDDI_DISABLE_REVERSE - MDDI_MSG_CRIT("No reverse link available\n"); - (void)wait; -#else - unsigned long flags; - boolean error = FALSE; - mddi_host_type host_idx = MDDI_HOST_PRIM; - mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); - - spin_lock_irqsave(&mddi_host_spin_lock, flags); - - /* turn on clock(s), if they have been disabled */ - mddi_host_enable_hclk(); - mddi_host_enable_io_clock(); - - if (wait) { - if (!mddi_rev_user.waiting) { - mddi_rev_user.waiting = TRUE; - INIT_COMPLETION(mddi_rev_user.done_comp); - } else - error = TRUE; - } - mddi_rev_encap_user_request = TRUE; - - if (pmhctl->rev_state == MDDI_REV_IDLE) { - /* attempt to send the reverse encapsulation now */ - mddi_host_type orig_host_idx = mddi_curr_host; - mddi_curr_host = host_idx; - mddi_issue_reverse_encapsulation(); - mddi_curr_host = orig_host_idx; - } - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - - if (error) { - MDDI_MSG_ERR("Reverse Encap request already in progress\n"); - } else if (wait) - wait_for_completion_killable(&(mddi_rev_user.done_comp)); -#endif -} - -/* ISR to be executed */ -boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type) -{ -#ifdef FEATURE_MDDI_DISABLE_REVERSE - MDDI_MSG_CRIT("No reverse link available\n"); - (void)handler; - (void)pkt_type; - return (FALSE); -#else - unsigned long flags; - uint16 hdlr; - boolean handler_set = FALSE; - boolean overwrite = FALSE; - mddi_host_type host_idx = MDDI_HOST_PRIM; - mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); - - /* Disable interrupts */ - spin_lock_irqsave(&mddi_host_spin_lock, flags); - - for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) { - if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) { - mddi_rev_pkt_handler[hdlr].handler = handler; - if (handler == NULL) { - /* clearing handler from table */ - mddi_rev_pkt_handler[hdlr].pkt_type = - INVALID_PKT_TYPE; - handler_set = TRUE; - if (pkt_type == 0x10) { /* video stream packet */ - /* ensure HCLK on to MDDI host core before register write */ - mddi_host_enable_hclk(); - /* No longer getting video, so reset rev encap size to default */ - pmhctl->rev_pkt_size = - MDDI_DEFAULT_REV_PKT_SIZE; - mddi_host_reg_out(REV_ENCAP_SZ, - pmhctl->rev_pkt_size); - } - } else { - /* already a handler for this packet */ - overwrite = TRUE; - } - break; - } - } - if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) { - /* assigning new handler */ - for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) { - if (mddi_rev_pkt_handler[hdlr].pkt_type == - INVALID_PKT_TYPE) { - if ((pkt_type == 0x10) && /* video stream packet */ - (pmhctl->rev_pkt_size < - MDDI_VIDEO_REV_PKT_SIZE)) { - /* ensure HCLK on to MDDI host core before register write */ - mddi_host_enable_hclk(); - /* Increase Rev Encap Size */ - pmhctl->rev_pkt_size = - MDDI_VIDEO_REV_PKT_SIZE; - mddi_host_reg_out(REV_ENCAP_SZ, - pmhctl->rev_pkt_size); - } - mddi_rev_pkt_handler[hdlr].handler = handler; - mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type; - handler_set = TRUE; - break; - } - } - } - - /* Restore interrupts */ - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - - if (overwrite) - MDDI_MSG_ERR("Overwriting previous rev packet handler\n"); - - return handler_set; - -#endif -} /* mddi_set_rev_handler */ - -void mddi_host_disable_hibernation(boolean disable) -{ - mddi_host_type host_idx = MDDI_HOST_PRIM; - mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]); - - if (disable) { - pmhctl->disable_hibernation = TRUE; - /* hibernation will be turned off by isr next time it is entered */ - } else { - if (pmhctl->disable_hibernation) { - unsigned long flags; - spin_lock_irqsave(&mddi_host_spin_lock, flags); - if (!MDDI_HOST_IS_HCLK_ON) - MDDI_HOST_ENABLE_HCLK; - mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1); - spin_unlock_irqrestore(&mddi_host_spin_lock, flags); - pmhctl->disable_hibernation = FALSE; - } - } -} - -void mddi_mhctl_remove(mddi_host_type host_idx) -{ - mddi_host_cntl_type *pmhctl; - - pmhctl = &(mhctl[host_idx]); - - dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr, - pmhctl->llist_dma_addr); - - dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE, - (void *)pmhctl->rev_data_buf, - pmhctl->rev_data_dma_addr); -} |