Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[sfrench/cifs-2.6.git] / drivers / staging / msm / mddihosti.c
1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License version 2 and
5  * only version 2 as published by the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/slab.h>
21 #include <linux/delay.h>
22 #include <linux/mm.h>
23 #include <linux/fb.h>
24 #include <linux/init.h>
25 #include <linux/ioport.h>
26 #include <linux/device.h>
27 #include <linux/dma-mapping.h>
28
29 #include "msm_fb_panel.h"
30 #include "mddihost.h"
31 #include "mddihosti.h"
32
33 #define FEATURE_MDDI_UNDERRUN_RECOVERY
34 #ifndef FEATURE_MDDI_DISABLE_REVERSE
35 static void mddi_read_rev_packet(byte *data_ptr);
36 #endif
37
38 struct timer_list mddi_host_timer;
39
40 #define MDDI_DEFAULT_TIMER_LENGTH 5000  /* 5 seconds */
41 uint32 mddi_rtd_frequency = 60000;      /* send RTD every 60 seconds */
42 uint32 mddi_client_status_frequency = 60000;    /* get status pkt every 60 secs */
43
44 boolean mddi_vsync_detect_enabled = FALSE;
45 mddi_gpio_info_type mddi_gpio;
46
47 uint32 mddi_host_core_version;
48 boolean mddi_debug_log_statistics = FALSE;
49 /* #define FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION */
50 /* default to TRUE in case MDP does not vote */
51 static boolean mddi_host_mdp_active_flag = TRUE;
52 static uint32 mddi_log_stats_counter;
53 uint32 mddi_log_stats_frequency = 4000;
54
55 #define MDDI_DEFAULT_REV_PKT_SIZE            0x20
56
57 #ifndef FEATURE_MDDI_DISABLE_REVERSE
58 static boolean mddi_rev_ptr_workaround = TRUE;
59 static uint32 mddi_reg_read_retry;
60 static uint32 mddi_reg_read_retry_max = 20;
61 static boolean mddi_enable_reg_read_retry = TRUE;
62 static boolean mddi_enable_reg_read_retry_once = FALSE;
63
64 #define MDDI_MAX_REV_PKT_SIZE                0x60
65
66 #define MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE  0x60
67
68 #define MDDI_VIDEO_REV_PKT_SIZE              0x40
69 #define MDDI_REV_BUFFER_SIZE  MDDI_MAX_REV_PKT_SIZE
70 static byte rev_packet_data[MDDI_MAX_REV_PKT_SIZE];
71 #endif /* FEATURE_MDDI_DISABLE_REVERSE */
72 /* leave these variables so graphics will compile */
73
74 #define MDDI_MAX_REV_DATA_SIZE  128
75 /*lint -d__align(x) */
76 boolean mddi_debug_clear_rev_data = TRUE;
77
78 uint32 *mddi_reg_read_value_ptr;
79
80 mddi_client_capability_type mddi_client_capability_pkt;
81 static boolean mddi_client_capability_request = FALSE;
82
83 #ifndef FEATURE_MDDI_DISABLE_REVERSE
84
85 #define MAX_MDDI_REV_HANDLERS 2
86 #define INVALID_PKT_TYPE 0xFFFF
87
88 typedef struct {
89         mddi_rev_handler_type handler;  /* ISR to be executed */
90         uint16 pkt_type;
91 } mddi_rev_pkt_handler_type;
92 static mddi_rev_pkt_handler_type mddi_rev_pkt_handler[MAX_MDDI_REV_HANDLERS] =
93     { {NULL, INVALID_PKT_TYPE}, {NULL, INVALID_PKT_TYPE} };
94
95 static boolean mddi_rev_encap_user_request = FALSE;
96 static mddi_linked_list_notify_type mddi_rev_user;
97
98 spinlock_t mddi_host_spin_lock;
99 extern uint32 mdp_in_processing;
100 #endif
101
102 typedef enum {
103         MDDI_REV_IDLE
104 #ifndef FEATURE_MDDI_DISABLE_REVERSE
105             , MDDI_REV_REG_READ_ISSUED,
106         MDDI_REV_REG_READ_SENT,
107         MDDI_REV_ENCAP_ISSUED,
108         MDDI_REV_STATUS_REQ_ISSUED,
109         MDDI_REV_CLIENT_CAP_ISSUED
110 #endif
111 } mddi_rev_link_state_type;
112
113 typedef enum {
114         MDDI_LINK_DISABLED,
115         MDDI_LINK_HIBERNATING,
116         MDDI_LINK_ACTIVATING,
117         MDDI_LINK_ACTIVE
118 } mddi_host_link_state_type;
119
120 typedef struct {
121         uint32 count;
122         uint32 in_count;
123         uint32 disp_req_count;
124         uint32 state_change_count;
125         uint32 ll_done_count;
126         uint32 rev_avail_count;
127         uint32 error_count;
128         uint32 rev_encap_count;
129         uint32 llist_ptr_write_1;
130         uint32 llist_ptr_write_2;
131 } mddi_host_int_type;
132
133 typedef struct {
134         uint32 fwd_crc_count;
135         uint32 rev_crc_count;
136         uint32 pri_underflow;
137         uint32 sec_underflow;
138         uint32 rev_overflow;
139         uint32 pri_overwrite;
140         uint32 sec_overwrite;
141         uint32 rev_overwrite;
142         uint32 dma_failure;
143         uint32 rtd_failure;
144         uint32 reg_read_failure;
145 #ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
146         uint32 pri_underrun_detected;
147 #endif
148 } mddi_host_stat_type;
149
150 typedef struct {
151         uint32 rtd_cnt;
152         uint32 rev_enc_cnt;
153         uint32 vid_cnt;
154         uint32 reg_acc_cnt;
155         uint32 cli_stat_cnt;
156         uint32 cli_cap_cnt;
157         uint32 reg_read_cnt;
158         uint32 link_active_cnt;
159         uint32 link_hibernate_cnt;
160         uint32 vsync_response_cnt;
161         uint32 fwd_crc_cnt;
162         uint32 rev_crc_cnt;
163 } mddi_log_params_struct_type;
164
165 typedef struct {
166         uint32 rtd_value;
167         uint32 rtd_counter;
168         uint32 client_status_cnt;
169         boolean rev_ptr_written;
170         uint8 *rev_ptr_start;
171         uint8 *rev_ptr_curr;
172         uint32 mddi_rev_ptr_write_val;
173         dma_addr_t rev_data_dma_addr;
174         uint16 rev_pkt_size;
175         mddi_rev_link_state_type rev_state;
176         mddi_host_link_state_type link_state;
177         mddi_host_driver_state_type driver_state;
178         boolean disable_hibernation;
179         uint32 saved_int_reg;
180         uint32 saved_int_en;
181         mddi_linked_list_type *llist_ptr;
182         dma_addr_t llist_dma_addr;
183         mddi_linked_list_type *llist_dma_ptr;
184         uint32 *rev_data_buf;
185         struct completion mddi_llist_avail_comp;
186         boolean mddi_waiting_for_llist_avail;
187         mddi_host_int_type int_type;
188         mddi_host_stat_type stats;
189         mddi_log_params_struct_type log_parms;
190         mddi_llist_info_type llist_info;
191         mddi_linked_list_notify_type llist_notify[MDDI_MAX_NUM_LLIST_ITEMS];
192 } mddi_host_cntl_type;
193
194 static mddi_host_type mddi_curr_host = MDDI_HOST_PRIM;
195 static mddi_host_cntl_type mhctl[MDDI_NUM_HOST_CORES];
196 mddi_linked_list_type *llist_extern[MDDI_NUM_HOST_CORES];
197 mddi_linked_list_type *llist_dma_extern[MDDI_NUM_HOST_CORES];
198 mddi_linked_list_notify_type *llist_extern_notify[MDDI_NUM_HOST_CORES];
199 static mddi_log_params_struct_type prev_parms[MDDI_NUM_HOST_CORES];
200
201 extern uint32 mdp_total_vdopkts;
202
203 static boolean mddi_host_io_clock_on = FALSE;
204 static boolean mddi_host_hclk_on = FALSE;
205
206 int int_mddi_pri_flag = FALSE;
207 int int_mddi_ext_flag = FALSE;
208
209 static void mddi_report_errors(uint32 int_reg)
210 {
211         mddi_host_type host_idx = mddi_curr_host;
212         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
213
214         if (int_reg & MDDI_INT_PRI_UNDERFLOW) {
215                 pmhctl->stats.pri_underflow++;
216                 MDDI_MSG_ERR("!!! MDDI Primary Underflow !!!\n");
217         }
218         if (int_reg & MDDI_INT_SEC_UNDERFLOW) {
219                 pmhctl->stats.sec_underflow++;
220                 MDDI_MSG_ERR("!!! MDDI Secondary Underflow !!!\n");
221         }
222 #ifndef FEATURE_MDDI_DISABLE_REVERSE
223         if (int_reg & MDDI_INT_REV_OVERFLOW) {
224                 pmhctl->stats.rev_overflow++;
225                 MDDI_MSG_ERR("!!! MDDI Reverse Overflow !!!\n");
226                 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
227                 mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
228
229         }
230         if (int_reg & MDDI_INT_CRC_ERROR)
231                 MDDI_MSG_ERR("!!! MDDI Reverse CRC Error !!!\n");
232 #endif
233         if (int_reg & MDDI_INT_PRI_OVERWRITE) {
234                 pmhctl->stats.pri_overwrite++;
235                 MDDI_MSG_ERR("!!! MDDI Primary Overwrite !!!\n");
236         }
237         if (int_reg & MDDI_INT_SEC_OVERWRITE) {
238                 pmhctl->stats.sec_overwrite++;
239                 MDDI_MSG_ERR("!!! MDDI Secondary Overwrite !!!\n");
240         }
241 #ifndef FEATURE_MDDI_DISABLE_REVERSE
242         if (int_reg & MDDI_INT_REV_OVERWRITE) {
243                 pmhctl->stats.rev_overwrite++;
244                 /* This will show up normally and is not a problem */
245                 MDDI_MSG_DEBUG("MDDI Reverse Overwrite!\n");
246         }
247         if (int_reg & MDDI_INT_RTD_FAILURE) {
248                 mddi_host_reg_outm(INTEN, MDDI_INT_RTD_FAILURE, 0);
249                 pmhctl->stats.rtd_failure++;
250                 MDDI_MSG_ERR("!!! MDDI RTD Failure !!!\n");
251         }
252 #endif
253         if (int_reg & MDDI_INT_DMA_FAILURE) {
254                 pmhctl->stats.dma_failure++;
255                 MDDI_MSG_ERR("!!! MDDI DMA Abort !!!\n");
256         }
257 }
258
259 static void mddi_host_enable_io_clock(void)
260 {
261         if (!MDDI_HOST_IS_IO_CLOCK_ON)
262                 MDDI_HOST_ENABLE_IO_CLOCK;
263 }
264
265 static void mddi_host_enable_hclk(void)
266 {
267
268         if (!MDDI_HOST_IS_HCLK_ON)
269                 MDDI_HOST_ENABLE_HCLK;
270 }
271
272 static void mddi_host_disable_io_clock(void)
273 {
274 #ifndef FEATURE_MDDI_HOST_IO_CLOCK_CONTROL_DISABLE
275         if (MDDI_HOST_IS_IO_CLOCK_ON)
276                 MDDI_HOST_DISABLE_IO_CLOCK;
277 #endif
278 }
279
280 static void mddi_host_disable_hclk(void)
281 {
282 #ifndef FEATURE_MDDI_HOST_HCLK_CONTROL_DISABLE
283         if (MDDI_HOST_IS_HCLK_ON)
284                 MDDI_HOST_DISABLE_HCLK;
285 #endif
286 }
287
288 static void mddi_vote_to_sleep(mddi_host_type host_idx, boolean sleep)
289 {
290         uint16 vote_mask;
291
292         if (host_idx == MDDI_HOST_PRIM)
293                 vote_mask = 0x01;
294         else
295                 vote_mask = 0x02;
296 }
297
298 static void mddi_report_state_change(uint32 int_reg)
299 {
300         mddi_host_type host_idx = mddi_curr_host;
301         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
302
303         if ((pmhctl->saved_int_reg & MDDI_INT_IN_HIBERNATION) &&
304             (pmhctl->saved_int_reg & MDDI_INT_LINK_ACTIVE)) {
305                 /* recover from condition where the io_clock was turned off by the
306                    clock driver during a transition to hibernation. The io_clock
307                    disable is to prevent MDP/MDDI underruns when changing ARM
308                    clock speeds. In the process of halting the ARM, the hclk
309                    divider needs to be set to 1. When it is set to 1, there is
310                    a small time (usecs) when hclk is off or slow, and this can
311                    cause an underrun. To prevent the underrun, clock driver turns
312                    off the MDDI io_clock before making the change. */
313                 mddi_host_reg_out(CMD, MDDI_CMD_POWERUP);
314         }
315
316         if (int_reg & MDDI_INT_LINK_ACTIVE) {
317                 pmhctl->link_state = MDDI_LINK_ACTIVE;
318                 pmhctl->log_parms.link_active_cnt++;
319                 pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
320                 MDDI_MSG_DEBUG("!!! MDDI Active RTD:0x%x!!!\n",
321                                pmhctl->rtd_value);
322                 /* now interrupt on hibernation */
323                 mddi_host_reg_outm(INTEN,
324                                    (MDDI_INT_IN_HIBERNATION |
325                                     MDDI_INT_LINK_ACTIVE),
326                                    MDDI_INT_IN_HIBERNATION);
327
328 #ifdef DEBUG_MDDIHOSTI
329                 /* if gpio interrupt is enabled, start polling at fastest
330                  * registered rate
331                  */
332                 if (mddi_gpio.polling_enabled) {
333                         timer_reg(&mddi_gpio_poll_timer,
334                 mddi_gpio_poll_timer_cb, 0, mddi_gpio.polling_interval, 0);
335                 }
336 #endif
337 #ifndef FEATURE_MDDI_DISABLE_REVERSE
338                 if (mddi_rev_ptr_workaround) {
339                         /* HW CR: need to reset reverse register stuff */
340                         pmhctl->rev_ptr_written = FALSE;
341                         pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
342                 }
343 #endif
344                 /* vote on sleep */
345                 mddi_vote_to_sleep(host_idx, FALSE);
346
347                 if (host_idx == MDDI_HOST_PRIM) {
348                         if (mddi_vsync_detect_enabled) {
349                                 /*
350                                  * Indicate to client specific code that vsync
351                                  * was enabled, but we did not detect a client
352                                  * intiated wakeup. The client specific
353                                  * handler can either reassert vsync detection,
354                                  * or treat this as a valid vsync.
355                                  */
356                                 mddi_client_lcd_vsync_detected(FALSE);
357                                 pmhctl->log_parms.vsync_response_cnt++;
358                         }
359                 }
360         }
361         if (int_reg & MDDI_INT_IN_HIBERNATION) {
362                 pmhctl->link_state = MDDI_LINK_HIBERNATING;
363                 pmhctl->log_parms.link_hibernate_cnt++;
364                 MDDI_MSG_DEBUG("!!! MDDI Hibernating !!!\n");
365                 /* now interrupt on link_active */
366 #ifdef FEATURE_MDDI_DISABLE_REVERSE
367                 mddi_host_reg_outm(INTEN,
368                                    (MDDI_INT_MDDI_IN |
369                                     MDDI_INT_IN_HIBERNATION |
370                                     MDDI_INT_LINK_ACTIVE),
371                                    MDDI_INT_LINK_ACTIVE);
372 #else
373                 mddi_host_reg_outm(INTEN,
374                                    (MDDI_INT_MDDI_IN |
375                                     MDDI_INT_IN_HIBERNATION |
376                                     MDDI_INT_LINK_ACTIVE),
377                                    (MDDI_INT_MDDI_IN | MDDI_INT_LINK_ACTIVE));
378
379                 pmhctl->rtd_counter = mddi_rtd_frequency;
380
381                 if (pmhctl->rev_state != MDDI_REV_IDLE) {
382                         /* a rev_encap will not wake up the link, so we do that here */
383                         pmhctl->link_state = MDDI_LINK_ACTIVATING;
384                         mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
385                 }
386 #endif
387
388                 if (pmhctl->disable_hibernation) {
389                         mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
390                         mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
391                         pmhctl->link_state = MDDI_LINK_ACTIVATING;
392                 }
393 #ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
394                 if ((pmhctl->llist_info.transmitting_start_idx !=
395                      UNASSIGNED_INDEX)
396                     &&
397                     ((pmhctl->
398                       saved_int_reg & (MDDI_INT_PRI_LINK_LIST_DONE |
399                                        MDDI_INT_PRI_PTR_READ)) ==
400                      MDDI_INT_PRI_PTR_READ)) {
401                         mddi_linked_list_type *llist_dma;
402                         llist_dma = pmhctl->llist_dma_ptr;
403                         /*
404                          * All indications are that we have not received a
405                          * linked list done interrupt, due to an underrun
406                          * condition. Recovery attempt is to send again.
407                          */
408                         dma_coherent_pre_ops();
409                         /* Write to primary pointer register again */
410                         mddi_host_reg_out(PRI_PTR,
411                                           &llist_dma[pmhctl->llist_info.
412                                                      transmitting_start_idx]);
413                         pmhctl->stats.pri_underrun_detected++;
414                 }
415 #endif
416
417                 /* vote on sleep */
418                 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
419                         mddi_vote_to_sleep(host_idx, TRUE);
420                 }
421
422 #ifdef DEBUG_MDDIHOSTI
423                 /* need to stop polling timer */
424                 if (mddi_gpio.polling_enabled) {
425                         (void) timer_clr(&mddi_gpio_poll_timer, T_NONE);
426                 }
427 #endif
428         }
429 }
430
431 void mddi_host_timer_service(unsigned long data)
432 {
433 #ifndef FEATURE_MDDI_DISABLE_REVERSE
434         unsigned long flags;
435 #endif
436         mddi_host_type host_idx;
437         mddi_host_cntl_type *pmhctl;
438
439         unsigned long time_ms = MDDI_DEFAULT_TIMER_LENGTH;
440         init_timer(&mddi_host_timer);
441         mddi_host_timer.function = mddi_host_timer_service;
442         mddi_host_timer.data = 0;
443
444         mddi_host_timer.expires = jiffies + ((time_ms * HZ) / 1000);
445         add_timer(&mddi_host_timer);
446
447         for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
448              host_idx++) {
449                 pmhctl = &(mhctl[host_idx]);
450                 mddi_log_stats_counter += (uint32) time_ms;
451 #ifndef FEATURE_MDDI_DISABLE_REVERSE
452                 pmhctl->rtd_counter += (uint32) time_ms;
453                 pmhctl->client_status_cnt += (uint32) time_ms;
454
455                 if (host_idx == MDDI_HOST_PRIM) {
456                         if (pmhctl->client_status_cnt >=
457                             mddi_client_status_frequency) {
458                                 if ((pmhctl->link_state ==
459                                      MDDI_LINK_HIBERNATING)
460                                     && (pmhctl->client_status_cnt >
461                                         mddi_client_status_frequency)) {
462                                         /*
463                                          * special case where we are hibernating
464                                          * and mddi_host_isr is not firing, so
465                                          * kick the link so that the status can
466                                          * be retrieved
467                                          */
468
469                                         /* need to wake up link before issuing
470                                          * rev encap command
471                                          */
472                                         MDDI_MSG_INFO("wake up link!\n");
473                                         spin_lock_irqsave(&mddi_host_spin_lock,
474                                                           flags);
475                                         mddi_host_enable_hclk();
476                                         mddi_host_enable_io_clock();
477                                         pmhctl->link_state =
478                                             MDDI_LINK_ACTIVATING;
479                                         mddi_host_reg_out(CMD,
480                                                           MDDI_CMD_LINK_ACTIVE);
481                                         spin_unlock_irqrestore
482                                             (&mddi_host_spin_lock, flags);
483                                 } else
484                                     if ((pmhctl->link_state == MDDI_LINK_ACTIVE)
485                                         && pmhctl->disable_hibernation) {
486                                         /*
487                                          * special case where we have disabled
488                                          * hibernation and mddi_host_isr
489                                          * is not firing, so enable interrupt
490                                          * for no pkts pending, which will
491                                          * generate an interrupt
492                                          */
493                                         MDDI_MSG_INFO("kick isr!\n");
494                                         spin_lock_irqsave(&mddi_host_spin_lock,
495                                                           flags);
496                                         mddi_host_enable_hclk();
497                                         mddi_host_reg_outm(INTEN,
498                                                            MDDI_INT_NO_CMD_PKTS_PEND,
499                                                            MDDI_INT_NO_CMD_PKTS_PEND);
500                                         spin_unlock_irqrestore
501                                             (&mddi_host_spin_lock, flags);
502                                 }
503                         }
504                 }
505 #endif /* #ifndef FEATURE_MDDI_DISABLE_REVERSE */
506         }
507
508         /* Check if logging is turned on */
509         for (host_idx = MDDI_HOST_PRIM; host_idx < MDDI_NUM_HOST_CORES;
510              host_idx++) {
511                 mddi_log_params_struct_type *prev_ptr = &(prev_parms[host_idx]);
512                 pmhctl = &(mhctl[host_idx]);
513
514                 if (mddi_debug_log_statistics) {
515
516                         /* get video pkt count from MDP, since MDDI sw cannot know this */
517                         pmhctl->log_parms.vid_cnt = mdp_total_vdopkts;
518
519                         if (mddi_log_stats_counter >= mddi_log_stats_frequency) {
520                                 /* mddi_log_stats_counter = 0; */
521                                 if (mddi_debug_log_statistics) {
522                                         MDDI_MSG_NOTICE
523                                             ("MDDI Statistics since last report:\n");
524                                         MDDI_MSG_NOTICE("  Packets sent:\n");
525                                         MDDI_MSG_NOTICE
526                                             ("    %d RTD packet(s)\n",
527                                              pmhctl->log_parms.rtd_cnt -
528                                              prev_ptr->rtd_cnt);
529                                         if (prev_ptr->rtd_cnt !=
530                                             pmhctl->log_parms.rtd_cnt) {
531                                                 unsigned long flags;
532                                                 spin_lock_irqsave
533                                                     (&mddi_host_spin_lock,
534                                                      flags);
535                                                 mddi_host_enable_hclk();
536                                                 pmhctl->rtd_value =
537                                                     mddi_host_reg_in(RTD_VAL);
538                                                 spin_unlock_irqrestore
539                                                     (&mddi_host_spin_lock,
540                                                      flags);
541                                                 MDDI_MSG_NOTICE
542                                                     ("      RTD value=%d\n",
543                                                      pmhctl->rtd_value);
544                                         }
545                                         MDDI_MSG_NOTICE
546                                             ("    %d VIDEO packets\n",
547                                              pmhctl->log_parms.vid_cnt -
548                                              prev_ptr->vid_cnt);
549                                         MDDI_MSG_NOTICE
550                                             ("    %d Register Access packets\n",
551                                              pmhctl->log_parms.reg_acc_cnt -
552                                              prev_ptr->reg_acc_cnt);
553                                         MDDI_MSG_NOTICE
554                                             ("    %d Reverse Encapsulation packet(s)\n",
555                                              pmhctl->log_parms.rev_enc_cnt -
556                                              prev_ptr->rev_enc_cnt);
557                                         if (prev_ptr->rev_enc_cnt !=
558                                             pmhctl->log_parms.rev_enc_cnt) {
559                                                 /* report # of reverse CRC errors */
560                                                 MDDI_MSG_NOTICE
561                                                     ("      %d reverse CRC errors detected\n",
562                                                      pmhctl->log_parms.
563                                                      rev_crc_cnt -
564                                                      prev_ptr->rev_crc_cnt);
565                                         }
566                                         MDDI_MSG_NOTICE
567                                             ("  Packets received:\n");
568                                         MDDI_MSG_NOTICE
569                                             ("    %d Client Status packets",
570                                              pmhctl->log_parms.cli_stat_cnt -
571                                              prev_ptr->cli_stat_cnt);
572                                         if (prev_ptr->cli_stat_cnt !=
573                                             pmhctl->log_parms.cli_stat_cnt) {
574                                                 MDDI_MSG_NOTICE
575                                                     ("      %d forward CRC errors reported\n",
576                                                      pmhctl->log_parms.
577                                                      fwd_crc_cnt -
578                                                      prev_ptr->fwd_crc_cnt);
579                                         }
580                                         MDDI_MSG_NOTICE
581                                             ("    %d Register Access Read packets\n",
582                                              pmhctl->log_parms.reg_read_cnt -
583                                              prev_ptr->reg_read_cnt);
584
585                                         if (pmhctl->link_state ==
586                                             MDDI_LINK_ACTIVE) {
587                                                 MDDI_MSG_NOTICE
588                                                     ("  Current Link Status: Active\n");
589                                         } else
590                                             if ((pmhctl->link_state ==
591                                                  MDDI_LINK_HIBERNATING)
592                                                 || (pmhctl->link_state ==
593                                                     MDDI_LINK_ACTIVATING)) {
594                                                 MDDI_MSG_NOTICE
595                                                     ("  Current Link Status: Hibernation\n");
596                                         } else {
597                                                 MDDI_MSG_NOTICE
598                                                     ("  Current Link Status: Inactive\n");
599                                         }
600                                         MDDI_MSG_NOTICE
601                                             ("    Active state entered %d times\n",
602                                              pmhctl->log_parms.link_active_cnt -
603                                              prev_ptr->link_active_cnt);
604                                         MDDI_MSG_NOTICE
605                                             ("    Hibernation state entered %d times\n",
606                                              pmhctl->log_parms.
607                                              link_hibernate_cnt -
608                                              prev_ptr->link_hibernate_cnt);
609                                 }
610                         }
611                         prev_parms[host_idx] = pmhctl->log_parms;
612                 }
613         }
614         if (mddi_log_stats_counter >= mddi_log_stats_frequency)
615                 mddi_log_stats_counter = 0;
616
617         return;
618 }                               /* mddi_host_timer_cb */
619
620 static void mddi_process_link_list_done(void)
621 {
622         mddi_host_type host_idx = mddi_curr_host;
623         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
624
625         /* normal forward linked list packet(s) were sent */
626         if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
627                 MDDI_MSG_ERR("**** getting LL done, but no list ****\n");
628         } else {
629                 uint16 idx;
630
631 #ifndef FEATURE_MDDI_DISABLE_REVERSE
632                 if (pmhctl->rev_state == MDDI_REV_REG_READ_ISSUED) {
633                         /* special case where a register read packet was sent */
634                         pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
635                         if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
636                                 MDDI_MSG_ERR
637                                     ("**** getting LL done, but no list ****\n");
638                         }
639                 }
640 #endif
641                 for (idx = pmhctl->llist_info.transmitting_start_idx;;) {
642                         uint16 next_idx = pmhctl->llist_notify[idx].next_idx;
643                         /* with reg read we don't release the waiting tcb until after
644                          * the reverse encapsulation has completed.
645                          */
646                         if (idx != pmhctl->llist_info.reg_read_idx) {
647                                 /* notify task that may be waiting on this completion */
648                                 if (pmhctl->llist_notify[idx].waiting) {
649                                         complete(&
650                                                  (pmhctl->llist_notify[idx].
651                                                   done_comp));
652                                 }
653                                 if (pmhctl->llist_notify[idx].done_cb != NULL) {
654                                         (*(pmhctl->llist_notify[idx].done_cb))
655                                             ();
656                                 }
657
658                                 pmhctl->llist_notify[idx].in_use = FALSE;
659                                 pmhctl->llist_notify[idx].waiting = FALSE;
660                                 pmhctl->llist_notify[idx].done_cb = NULL;
661                                 if (idx < MDDI_NUM_DYNAMIC_LLIST_ITEMS) {
662                                         /* static LLIST items are configured only once */
663                                         pmhctl->llist_notify[idx].next_idx =
664                                             UNASSIGNED_INDEX;
665                                 }
666                                 /*
667                                  * currently, all linked list packets are
668                                  * register access, so we can increment the
669                                  * counter for that packet type here.
670                                  */
671                                 pmhctl->log_parms.reg_acc_cnt++;
672                         }
673                         if (idx == pmhctl->llist_info.transmitting_end_idx)
674                                 break;
675                         idx = next_idx;
676                         if (idx == UNASSIGNED_INDEX)
677                                 MDDI_MSG_CRIT("MDDI linked list corruption!\n");
678                 }
679
680                 pmhctl->llist_info.transmitting_start_idx = UNASSIGNED_INDEX;
681                 pmhctl->llist_info.transmitting_end_idx = UNASSIGNED_INDEX;
682
683                 if (pmhctl->mddi_waiting_for_llist_avail) {
684                         if (!
685                             (pmhctl->
686                              llist_notify[pmhctl->llist_info.next_free_idx].
687                              in_use)) {
688                                 pmhctl->mddi_waiting_for_llist_avail = FALSE;
689                                 complete(&(pmhctl->mddi_llist_avail_comp));
690                         }
691                 }
692         }
693
694         /* Turn off MDDI_INT_PRI_LINK_LIST_DONE interrupt */
695         mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE, 0);
696
697 }
698
699 static void mddi_queue_forward_linked_list(void)
700 {
701         uint16 first_pkt_index;
702         mddi_linked_list_type *llist_dma;
703         mddi_host_type host_idx = mddi_curr_host;
704         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
705         llist_dma = pmhctl->llist_dma_ptr;
706
707         first_pkt_index = UNASSIGNED_INDEX;
708
709         if (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) {
710 #ifndef FEATURE_MDDI_DISABLE_REVERSE
711                 if (pmhctl->llist_info.reg_read_waiting) {
712                         if (pmhctl->rev_state == MDDI_REV_IDLE) {
713                                 /*
714                                  * we have a register read to send and
715                                  * can send it now
716                                  */
717                                 pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
718                                 mddi_reg_read_retry = 0;
719                                 first_pkt_index =
720                                     pmhctl->llist_info.waiting_start_idx;
721                                 pmhctl->llist_info.reg_read_waiting = FALSE;
722                         }
723                 } else
724 #endif
725                 {
726                         /*
727                          * not register read to worry about, go ahead and write
728                          * anything that may be on the waiting list.
729                          */
730                         first_pkt_index = pmhctl->llist_info.waiting_start_idx;
731                 }
732         }
733
734         if (first_pkt_index != UNASSIGNED_INDEX) {
735                 pmhctl->llist_info.transmitting_start_idx =
736                     pmhctl->llist_info.waiting_start_idx;
737                 pmhctl->llist_info.transmitting_end_idx =
738                     pmhctl->llist_info.waiting_end_idx;
739                 pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
740                 pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
741
742                 /* write to the primary pointer register */
743                 MDDI_MSG_DEBUG("MDDI writing primary ptr with idx=%d\n",
744                                first_pkt_index);
745
746                 pmhctl->int_type.llist_ptr_write_2++;
747
748                 dma_coherent_pre_ops();
749                 mddi_host_reg_out(PRI_PTR, &llist_dma[first_pkt_index]);
750
751                 /* enable interrupt when complete */
752                 mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
753                                    MDDI_INT_PRI_LINK_LIST_DONE);
754
755         }
756
757 }
758
759 #ifndef FEATURE_MDDI_DISABLE_REVERSE
760 static void mddi_read_rev_packet(byte *data_ptr)
761 {
762         uint16 i, length;
763         mddi_host_type host_idx = mddi_curr_host;
764         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
765
766         uint8 *rev_ptr_overflow =
767             (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE);
768
769         /* first determine the length and handle invalid lengths */
770         length = *pmhctl->rev_ptr_curr++;
771         if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
772                 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
773         length |= ((*pmhctl->rev_ptr_curr++) << 8);
774         if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
775                 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
776         if (length > (pmhctl->rev_pkt_size - 2)) {
777                 MDDI_MSG_ERR("Invalid rev pkt length %d\n", length);
778                 /* rev_pkt_size should always be <= rev_ptr_size so limit to packet size */
779                 length = pmhctl->rev_pkt_size - 2;
780         }
781
782         /* If the data pointer is NULL, just increment the pmhctl->rev_ptr_curr.
783          * Loop around if necessary. Don't bother reading the data.
784          */
785         if (data_ptr == NULL) {
786                 pmhctl->rev_ptr_curr += length;
787                 if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
788                         pmhctl->rev_ptr_curr -= MDDI_REV_BUFFER_SIZE;
789                 return;
790         }
791
792         data_ptr[0] = length & 0x0ff;
793         data_ptr[1] = length >> 8;
794         data_ptr += 2;
795         /* copy the data to data_ptr byte-at-a-time */
796         for (i = 0; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow);
797              i++)
798                 *data_ptr++ = *pmhctl->rev_ptr_curr++;
799         if (pmhctl->rev_ptr_curr >= rev_ptr_overflow)
800                 pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
801         for (; (i < length) && (pmhctl->rev_ptr_curr < rev_ptr_overflow); i++)
802                 *data_ptr++ = *pmhctl->rev_ptr_curr++;
803 }
804
805 static void mddi_process_rev_packets(void)
806 {
807         uint32 rev_packet_count;
808         word i;
809         uint32 crc_errors;
810         boolean mddi_reg_read_successful = FALSE;
811         mddi_host_type host_idx = mddi_curr_host;
812         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
813
814         pmhctl->log_parms.rev_enc_cnt++;
815         if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
816             (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED) &&
817             (pmhctl->rev_state != MDDI_REV_CLIENT_CAP_ISSUED)) {
818                 MDDI_MSG_ERR("Wrong state %d for reverse int\n",
819                              pmhctl->rev_state);
820         }
821         /* Turn off MDDI_INT_REV_AVAIL interrupt */
822         mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL, 0);
823
824         /* Clear rev data avail int */
825         mddi_host_reg_out(INT, MDDI_INT_REV_DATA_AVAIL);
826
827         /* Get Number of packets */
828         rev_packet_count = mddi_host_reg_in(REV_PKT_CNT);
829
830 #ifndef T_MSM7500
831         /* Clear out rev packet counter */
832         mddi_host_reg_out(REV_PKT_CNT, 0x0000);
833 #endif
834
835 #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
836         if ((pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) &&
837             (rev_packet_count > 0) &&
838             (mddi_host_core_version == 0x28 ||
839              mddi_host_core_version == 0x30)) {
840
841                 uint32 int_reg;
842                 uint32 max_count = 0;
843
844                 mddi_host_reg_out(REV_PTR, pmhctl->mddi_rev_ptr_write_val);
845                 int_reg = mddi_host_reg_in(INT);
846                 while ((int_reg & 0x100000) == 0) {
847                         udelay(3);
848                         int_reg = mddi_host_reg_in(INT);
849                         if (++max_count > 100)
850                                 break;
851                 }
852         }
853 #endif
854
855         /* Get CRC error count */
856         crc_errors = mddi_host_reg_in(REV_CRC_ERR);
857         if (crc_errors != 0) {
858                 pmhctl->log_parms.rev_crc_cnt += crc_errors;
859                 pmhctl->stats.rev_crc_count += crc_errors;
860                 MDDI_MSG_ERR("!!! MDDI %d Reverse CRC Error(s) !!!\n",
861                              crc_errors);
862 #ifndef T_MSM7500
863                 /* Clear CRC error count */
864                 mddi_host_reg_out(REV_CRC_ERR, 0x0000);
865 #endif
866                 /* also issue an RTD to attempt recovery */
867                 pmhctl->rtd_counter = mddi_rtd_frequency;
868         }
869
870         pmhctl->rtd_value = mddi_host_reg_in(RTD_VAL);
871
872         MDDI_MSG_DEBUG("MDDI rev pkt cnt=%d, ptr=0x%x, RTD:0x%x\n",
873                        rev_packet_count,
874                        pmhctl->rev_ptr_curr - pmhctl->rev_ptr_start,
875                        pmhctl->rtd_value);
876
877         if (rev_packet_count >= 1) {
878                 mddi_invalidate_cache_lines((uint32 *) pmhctl->rev_ptr_start,
879                                             MDDI_REV_BUFFER_SIZE);
880         }
881         /* order the reads */
882         dma_coherent_post_ops();
883         for (i = 0; i < rev_packet_count; i++) {
884                 mddi_rev_packet_type *rev_pkt_ptr;
885
886                 mddi_read_rev_packet(rev_packet_data);
887
888                 rev_pkt_ptr = (mddi_rev_packet_type *) rev_packet_data;
889
890                 if (rev_pkt_ptr->packet_length > pmhctl->rev_pkt_size) {
891                         MDDI_MSG_ERR("!!!invalid packet size: %d\n",
892                                      rev_pkt_ptr->packet_length);
893                 }
894
895                 MDDI_MSG_DEBUG("MDDI rev pkt 0x%x size 0x%x\n",
896                                rev_pkt_ptr->packet_type,
897                                rev_pkt_ptr->packet_length);
898
899                 /* Do whatever you want to do with the data based on the packet type */
900                 switch (rev_pkt_ptr->packet_type) {
901                 case 66:        /* Client Capability */
902                         {
903                                 mddi_client_capability_type
904                                     *client_capability_pkt_ptr;
905
906                                 client_capability_pkt_ptr =
907                                     (mddi_client_capability_type *)
908                                     rev_packet_data;
909                                 MDDI_MSG_NOTICE
910                                     ("Client Capability: Week=%d, Year=%d\n",
911                                      client_capability_pkt_ptr->
912                                      Week_of_Manufacture,
913                                      client_capability_pkt_ptr->
914                                      Year_of_Manufacture);
915                                 memcpy((void *)&mddi_client_capability_pkt,
916                                        (void *)rev_packet_data,
917                                        sizeof(mddi_client_capability_type));
918                                 pmhctl->log_parms.cli_cap_cnt++;
919                         }
920                         break;
921
922                 case 70:        /* Display Status */
923                         {
924                                 mddi_client_status_type *client_status_pkt_ptr;
925
926                                 client_status_pkt_ptr =
927                                     (mddi_client_status_type *) rev_packet_data;
928                                 if ((client_status_pkt_ptr->crc_error_count !=
929                                      0)
930                                     || (client_status_pkt_ptr->
931                                         reverse_link_request != 0)) {
932                                         MDDI_MSG_ERR
933                                             ("Client Status: RevReq=%d, CrcErr=%d\n",
934                                              client_status_pkt_ptr->
935                                              reverse_link_request,
936                                              client_status_pkt_ptr->
937                                              crc_error_count);
938                                 } else {
939                                         MDDI_MSG_DEBUG
940                                             ("Client Status: RevReq=%d, CrcErr=%d\n",
941                                              client_status_pkt_ptr->
942                                              reverse_link_request,
943                                              client_status_pkt_ptr->
944                                              crc_error_count);
945                                 }
946                                 pmhctl->log_parms.fwd_crc_cnt +=
947                                     client_status_pkt_ptr->crc_error_count;
948                                 pmhctl->stats.fwd_crc_count +=
949                                     client_status_pkt_ptr->crc_error_count;
950                                 pmhctl->log_parms.cli_stat_cnt++;
951                         }
952                         break;
953
954                 case 146:       /* register access packet */
955                         {
956                                 mddi_register_access_packet_type
957                                     * regacc_pkt_ptr;
958
959                                 regacc_pkt_ptr =
960                                     (mddi_register_access_packet_type *)
961                                     rev_packet_data;
962
963                                 MDDI_MSG_DEBUG
964                                     ("Reg Acc parse reg=0x%x, value=0x%x\n",
965                                      regacc_pkt_ptr->register_address,
966                                      regacc_pkt_ptr->register_data_list);
967
968                                 /* Copy register value to location passed in */
969                                 if (mddi_reg_read_value_ptr) {
970 #if defined(T_MSM6280) && !defined(T_MSM7200)
971                                         /* only least significant 16 bits are valid with 6280 */
972                                         *mddi_reg_read_value_ptr =
973                                             regacc_pkt_ptr->
974                                             register_data_list & 0x0000ffff;
975 #else
976                                         *mddi_reg_read_value_ptr =
977                                             regacc_pkt_ptr->register_data_list;
978 #endif
979                                         mddi_reg_read_successful = TRUE;
980                                         mddi_reg_read_value_ptr = NULL;
981                                 }
982
983 #ifdef DEBUG_MDDIHOSTI
984                                 if ((mddi_gpio.polling_enabled) &&
985                                     (regacc_pkt_ptr->register_address ==
986                                      mddi_gpio.polling_reg)) {
987                                         /*
988                                          * ToDo: need to call Linux GPIO call
989                                          * here...
990                                          */
991                                          mddi_client_lcd_gpio_poll(
992                                          regacc_pkt_ptr->register_data_list);
993                                 }
994 #endif
995                                 pmhctl->log_parms.reg_read_cnt++;
996                         }
997                         break;
998
999                 default:        /* any other packet */
1000                         {
1001                                 uint16 hdlr;
1002
1003                                 for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS;
1004                                      hdlr++) {
1005                                         if (mddi_rev_pkt_handler[hdlr].
1006                                             pkt_type ==
1007                                             rev_pkt_ptr->packet_type) {
1008                                                 (*
1009                                                  (mddi_rev_pkt_handler[hdlr].
1010                                                   handler)) (rev_pkt_ptr);
1011                                         /* pmhctl->rev_state = MDDI_REV_IDLE; */
1012                                                 break;
1013                                         }
1014                                 }
1015                                 if (hdlr >= MAX_MDDI_REV_HANDLERS)
1016                                         MDDI_MSG_ERR("MDDI unknown rev pkt\n");
1017                         }
1018                         break;
1019                 }
1020         }
1021         if ((pmhctl->rev_ptr_curr + pmhctl->rev_pkt_size) >=
1022             (pmhctl->rev_ptr_start + MDDI_REV_BUFFER_SIZE)) {
1023                 pmhctl->rev_ptr_written = FALSE;
1024         }
1025
1026         if (pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) {
1027                 pmhctl->rev_state = MDDI_REV_IDLE;
1028                 if (mddi_rev_user.waiting) {
1029                         mddi_rev_user.waiting = FALSE;
1030                         complete(&(mddi_rev_user.done_comp));
1031                 } else if (pmhctl->llist_info.reg_read_idx == UNASSIGNED_INDEX) {
1032                         MDDI_MSG_ERR
1033                             ("Reverse Encap state, but no reg read in progress\n");
1034                 } else {
1035                         if ((!mddi_reg_read_successful) &&
1036                             (mddi_reg_read_retry < mddi_reg_read_retry_max) &&
1037                             (mddi_enable_reg_read_retry)) {
1038                                 /*
1039                                  * There is a race condition that can happen
1040                                  * where the reverse encapsulation message is
1041                                  * sent out by the MDDI host before the register
1042                                  * read packet is sent. As a work-around for
1043                                  * that problem we issue the reverse
1044                                  * encapsulation one more time before giving up.
1045                                  */
1046                                 if (mddi_enable_reg_read_retry_once)
1047                                         mddi_reg_read_retry =
1048                                             mddi_reg_read_retry_max;
1049                                 pmhctl->rev_state = MDDI_REV_REG_READ_SENT;
1050                                 pmhctl->stats.reg_read_failure++;
1051                         } else {
1052                                 uint16 reg_read_idx =
1053                                     pmhctl->llist_info.reg_read_idx;
1054
1055                                 mddi_reg_read_retry = 0;
1056                                 if (pmhctl->llist_notify[reg_read_idx].waiting) {
1057                                         complete(&
1058                                                  (pmhctl->
1059                                                   llist_notify[reg_read_idx].
1060                                                   done_comp));
1061                                 }
1062                                 pmhctl->llist_info.reg_read_idx =
1063                                     UNASSIGNED_INDEX;
1064                                 if (pmhctl->llist_notify[reg_read_idx].
1065                                     done_cb != NULL) {
1066                                         (*
1067                                          (pmhctl->llist_notify[reg_read_idx].
1068                                           done_cb)) ();
1069                                 }
1070                                 pmhctl->llist_notify[reg_read_idx].next_idx =
1071                                     UNASSIGNED_INDEX;
1072                                 pmhctl->llist_notify[reg_read_idx].in_use =
1073                                     FALSE;
1074                                 pmhctl->llist_notify[reg_read_idx].waiting =
1075                                     FALSE;
1076                                 pmhctl->llist_notify[reg_read_idx].done_cb =
1077                                     NULL;
1078                                 if (!mddi_reg_read_successful)
1079                                         pmhctl->stats.reg_read_failure++;
1080                         }
1081                 }
1082         } else if (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED) {
1083 #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
1084                 if (mddi_host_core_version == 0x28 ||
1085                     mddi_host_core_version == 0x30) {
1086                         mddi_host_reg_out(FIFO_ALLOC, 0x00);
1087                         pmhctl->rev_ptr_written = TRUE;
1088                         mddi_host_reg_out(REV_PTR,
1089                                 pmhctl->mddi_rev_ptr_write_val);
1090                         pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
1091                         mddi_host_reg_out(CMD, 0xC00);
1092                 }
1093 #endif
1094
1095                 if (mddi_rev_user.waiting) {
1096                         mddi_rev_user.waiting = FALSE;
1097                         complete(&(mddi_rev_user.done_comp));
1098                 }
1099                 pmhctl->rev_state = MDDI_REV_IDLE;
1100         } else {
1101                 pmhctl->rev_state = MDDI_REV_IDLE;
1102         }
1103
1104         /* pmhctl->rev_state = MDDI_REV_IDLE; */
1105
1106         /* Re-enable interrupt */
1107         mddi_host_reg_outm(INTEN, MDDI_INT_REV_DATA_AVAIL,
1108                            MDDI_INT_REV_DATA_AVAIL);
1109
1110 }
1111
1112 static void mddi_issue_reverse_encapsulation(void)
1113 {
1114         mddi_host_type host_idx = mddi_curr_host;
1115         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1116         /* Only issue a reverse encapsulation packet if:
1117          * 1) another reverse is not in progress (MDDI_REV_IDLE).
1118          * 2) a register read has been sent (MDDI_REV_REG_READ_SENT).
1119          * 3) forward is not in progress, because of a hw bug in client that
1120          *    causes forward crc errors on packet immediately after rev encap.
1121          */
1122         if (((pmhctl->rev_state == MDDI_REV_IDLE) ||
1123              (pmhctl->rev_state == MDDI_REV_REG_READ_SENT)) &&
1124             (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
1125             (!mdp_in_processing)) {
1126                 uint32 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
1127
1128                 if ((pmhctl->rev_state == MDDI_REV_REG_READ_SENT) ||
1129                     (mddi_rev_encap_user_request == TRUE)) {
1130                         mddi_host_enable_io_clock();
1131                         if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1132                                 /* need to wake up link before issuing rev encap command */
1133                                 MDDI_MSG_DEBUG("wake up link!\n");
1134                                 pmhctl->link_state = MDDI_LINK_ACTIVATING;
1135                                 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
1136                         } else {
1137                                 if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
1138                                         MDDI_MSG_DEBUG
1139                                             ("mddi sending RTD command!\n");
1140                                         mddi_host_reg_out(CMD,
1141                                                           MDDI_CMD_SEND_RTD);
1142                                         pmhctl->rtd_counter = 0;
1143                                         pmhctl->log_parms.rtd_cnt++;
1144                                 }
1145                                 if (pmhctl->rev_state != MDDI_REV_REG_READ_SENT) {
1146                                         /* this is generic reverse request by user, so
1147                                          * reset the waiting flag. */
1148                                         mddi_rev_encap_user_request = FALSE;
1149                                 }
1150                                 /* link is active so send reverse encap to get register read results */
1151                                 pmhctl->rev_state = MDDI_REV_ENCAP_ISSUED;
1152                                 mddi_command = MDDI_CMD_SEND_REV_ENCAP;
1153                                 MDDI_MSG_DEBUG("sending rev encap!\n");
1154                         }
1155                 } else
1156                     if ((pmhctl->client_status_cnt >=
1157                          mddi_client_status_frequency)
1158                         || mddi_client_capability_request) {
1159                         mddi_host_enable_io_clock();
1160                         if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1161                                 /* only wake up the link if it client status is overdue */
1162                                 if ((pmhctl->client_status_cnt >=
1163                                      (mddi_client_status_frequency * 2))
1164                                     || mddi_client_capability_request) {
1165                                         /* need to wake up link before issuing rev encap command */
1166                                         MDDI_MSG_DEBUG("wake up link!\n");
1167                                         pmhctl->link_state =
1168                                             MDDI_LINK_ACTIVATING;
1169                                         mddi_host_reg_out(CMD,
1170                                                           MDDI_CMD_LINK_ACTIVE);
1171                                 }
1172                         } else {
1173                                 if (pmhctl->rtd_counter >= mddi_rtd_frequency) {
1174                                         MDDI_MSG_DEBUG
1175                                             ("mddi sending RTD command!\n");
1176                                         mddi_host_reg_out(CMD,
1177                                                           MDDI_CMD_SEND_RTD);
1178                                         pmhctl->rtd_counter = 0;
1179                                         pmhctl->log_parms.rtd_cnt++;
1180                                 }
1181                                 /* periodically get client status */
1182                                 MDDI_MSG_DEBUG
1183                                     ("mddi sending rev enc! (get status)\n");
1184                                 if (mddi_client_capability_request) {
1185                                         pmhctl->rev_state =
1186                                             MDDI_REV_CLIENT_CAP_ISSUED;
1187                                         mddi_command = MDDI_CMD_GET_CLIENT_CAP;
1188                                         mddi_client_capability_request = FALSE;
1189                                 } else {
1190                                         pmhctl->rev_state =
1191                                             MDDI_REV_STATUS_REQ_ISSUED;
1192                                         pmhctl->client_status_cnt = 0;
1193                                         mddi_command =
1194                                             MDDI_CMD_GET_CLIENT_STATUS;
1195                                 }
1196                         }
1197                 }
1198                 if ((pmhctl->rev_state == MDDI_REV_ENCAP_ISSUED) ||
1199                     (pmhctl->rev_state == MDDI_REV_STATUS_REQ_ISSUED) ||
1200                     (pmhctl->rev_state == MDDI_REV_CLIENT_CAP_ISSUED)) {
1201                         pmhctl->int_type.rev_encap_count++;
1202 #if defined(T_MSM6280) && !defined(T_MSM7200)
1203                         mddi_rev_pointer_written = TRUE;
1204                         mddi_host_reg_out(REV_PTR, mddi_rev_ptr_write_val);
1205                         mddi_rev_ptr_curr = mddi_rev_ptr_start;
1206                         /* force new rev ptr command */
1207                         mddi_host_reg_out(CMD, 0xC00);
1208 #else
1209                         if (!pmhctl->rev_ptr_written) {
1210                                 MDDI_MSG_DEBUG("writing reverse pointer!\n");
1211                                 pmhctl->rev_ptr_written = TRUE;
1212 #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
1213                                 if ((pmhctl->rev_state ==
1214                                      MDDI_REV_CLIENT_CAP_ISSUED) &&
1215                                     (mddi_host_core_version == 0x28 ||
1216                                      mddi_host_core_version == 0x30)) {
1217                                         pmhctl->rev_ptr_written = FALSE;
1218                                         mddi_host_reg_out(FIFO_ALLOC, 0x02);
1219                                 } else
1220                                         mddi_host_reg_out(REV_PTR,
1221                                                   pmhctl->
1222                                                   mddi_rev_ptr_write_val);
1223 #else
1224                                 mddi_host_reg_out(REV_PTR,
1225                                                   pmhctl->
1226                                                   mddi_rev_ptr_write_val);
1227 #endif
1228                         }
1229 #endif
1230                         if (mddi_debug_clear_rev_data) {
1231                                 uint16 i;
1232                                 for (i = 0; i < MDDI_MAX_REV_DATA_SIZE / 4; i++)
1233                                         pmhctl->rev_data_buf[i] = 0xdddddddd;
1234                                 /* clean cache */
1235                                 mddi_flush_cache_lines(pmhctl->rev_data_buf,
1236                                                        MDDI_MAX_REV_DATA_SIZE);
1237                         }
1238
1239                         /* send reverse encapsulation to get needed data */
1240                         mddi_host_reg_out(CMD, mddi_command);
1241                 }
1242         }
1243
1244 }
1245
1246 static void mddi_process_client_initiated_wakeup(void)
1247 {
1248         mddi_host_type host_idx = mddi_curr_host;
1249         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1250
1251         /* Disable MDDI_INT Interrupt, we detect client initiated wakeup one
1252          * time for each entry into hibernation */
1253         mddi_host_reg_outm(INTEN, MDDI_INT_MDDI_IN, 0);
1254
1255         if (host_idx == MDDI_HOST_PRIM) {
1256                 if (mddi_vsync_detect_enabled) {
1257                         mddi_host_enable_io_clock();
1258 #ifndef MDDI_HOST_DISP_LISTEN
1259                         /* issue command to bring up link */
1260                         /* need to do this to clear the vsync condition */
1261                         if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1262                                 pmhctl->link_state = MDDI_LINK_ACTIVATING;
1263                                 mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
1264                         }
1265 #endif
1266                         /*
1267                          * Indicate to client specific code that vsync was
1268                          * enabled, and we did not detect a client initiated
1269                          * wakeup. The client specific handler can clear the
1270                          * condition if necessary to prevent subsequent
1271                          * client initiated wakeups.
1272                          */
1273                         mddi_client_lcd_vsync_detected(TRUE);
1274                         pmhctl->log_parms.vsync_response_cnt++;
1275                         MDDI_MSG_NOTICE("MDDI_INT_IN condition\n");
1276
1277                 }
1278         }
1279
1280         if (mddi_gpio.polling_enabled) {
1281                 mddi_host_enable_io_clock();
1282                 /* check interrupt status now */
1283                 (void)mddi_queue_register_read_int(mddi_gpio.polling_reg,
1284                                                    &mddi_gpio.polling_val);
1285         }
1286 }
1287 #endif /* FEATURE_MDDI_DISABLE_REVERSE */
1288
1289 static void mddi_host_isr(void)
1290 {
1291         uint32 int_reg, int_en;
1292 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1293         uint32 status_reg;
1294 #endif
1295         mddi_host_type host_idx = mddi_curr_host;
1296         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1297
1298         if (!MDDI_HOST_IS_HCLK_ON) {
1299                 MDDI_HOST_ENABLE_HCLK;
1300                 MDDI_MSG_DEBUG("HCLK disabled, but isr is firing\n");
1301         }
1302         int_reg = mddi_host_reg_in(INT);
1303         int_en = mddi_host_reg_in(INTEN);
1304         pmhctl->saved_int_reg = int_reg;
1305         pmhctl->saved_int_en = int_en;
1306         int_reg = int_reg & int_en;
1307         pmhctl->int_type.count++;
1308
1309
1310 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1311         status_reg = mddi_host_reg_in(STAT);
1312
1313         if ((int_reg & MDDI_INT_MDDI_IN) ||
1314             ((int_en & MDDI_INT_MDDI_IN) &&
1315              ((int_reg == 0) || (status_reg & MDDI_STAT_CLIENT_WAKEUP_REQ)))) {
1316                 /*
1317                  * The MDDI_IN condition will clear itself, and so it is
1318                  * possible that MDDI_IN was the reason for the isr firing,
1319                  * even though the interrupt register does not have the
1320                  * MDDI_IN bit set. To check if this was the case we need to
1321                  * look at the status register bit that signifies a client
1322                  * initiated wakeup. If the status register bit is set, as well
1323                  * as the MDDI_IN interrupt enabled, then we treat this as a
1324                  * client initiated wakeup.
1325                  */
1326                 if (int_reg & MDDI_INT_MDDI_IN)
1327                         pmhctl->int_type.in_count++;
1328                 mddi_process_client_initiated_wakeup();
1329         }
1330 #endif
1331
1332         if (int_reg & MDDI_INT_LINK_STATE_CHANGES) {
1333                 pmhctl->int_type.state_change_count++;
1334                 mddi_report_state_change(int_reg);
1335         }
1336
1337         if (int_reg & MDDI_INT_PRI_LINK_LIST_DONE) {
1338                 pmhctl->int_type.ll_done_count++;
1339                 mddi_process_link_list_done();
1340         }
1341 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1342         if (int_reg & MDDI_INT_REV_DATA_AVAIL) {
1343                 pmhctl->int_type.rev_avail_count++;
1344                 mddi_process_rev_packets();
1345         }
1346 #endif
1347
1348         if (int_reg & MDDI_INT_ERROR_CONDITIONS) {
1349                 pmhctl->int_type.error_count++;
1350                 mddi_report_errors(int_reg);
1351
1352                 mddi_host_reg_out(INT, int_reg & MDDI_INT_ERROR_CONDITIONS);
1353         }
1354 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1355         mddi_issue_reverse_encapsulation();
1356
1357         if ((pmhctl->rev_state != MDDI_REV_ENCAP_ISSUED) &&
1358             (pmhctl->rev_state != MDDI_REV_STATUS_REQ_ISSUED))
1359 #endif
1360                 /* don't want simultaneous reverse and forward with Eagle */
1361                 mddi_queue_forward_linked_list();
1362
1363         if (int_reg & MDDI_INT_NO_CMD_PKTS_PEND) {
1364                 /* this interrupt is used to kick the isr when hibernation is disabled */
1365                 mddi_host_reg_outm(INTEN, MDDI_INT_NO_CMD_PKTS_PEND, 0);
1366         }
1367
1368         if ((!mddi_host_mdp_active_flag) &&
1369             (!mddi_vsync_detect_enabled) &&
1370             (pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
1371             (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
1372             (pmhctl->rev_state == MDDI_REV_IDLE)) {
1373                 if (pmhctl->link_state == MDDI_LINK_HIBERNATING) {
1374                         mddi_host_disable_io_clock();
1375                         mddi_host_disable_hclk();
1376                 }
1377 #ifdef FEATURE_MDDI_HOST_ENABLE_EARLY_HIBERNATION
1378                 else if ((pmhctl->link_state == MDDI_LINK_ACTIVE) &&
1379                          (!pmhctl->disable_hibernation)) {
1380                         mddi_host_reg_out(CMD, MDDI_CMD_POWERDOWN);
1381                 }
1382 #endif
1383         }
1384 }
1385
1386 static void mddi_host_isr_primary(void)
1387 {
1388         mddi_curr_host = MDDI_HOST_PRIM;
1389         mddi_host_isr();
1390 }
1391
1392 irqreturn_t mddi_pmdh_isr_proxy(int irq, void *ptr)
1393 {
1394         mddi_host_isr_primary();
1395         return IRQ_HANDLED;
1396 }
1397
1398 static void mddi_host_isr_external(void)
1399 {
1400         mddi_curr_host = MDDI_HOST_EXT;
1401         mddi_host_isr();
1402         mddi_curr_host = MDDI_HOST_PRIM;
1403 }
1404
1405 irqreturn_t mddi_emdh_isr_proxy(int irq, void *ptr)
1406 {
1407         mddi_host_isr_external();
1408         return IRQ_HANDLED;
1409 }
1410
1411 static void mddi_host_initialize_registers(mddi_host_type host_idx)
1412 {
1413         uint32 pad_reg_val;
1414         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1415
1416         if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
1417                 return;
1418
1419         /* turn on HCLK to MDDI host core */
1420         mddi_host_enable_hclk();
1421
1422         /* MDDI Reset command */
1423         mddi_host_reg_out(CMD, MDDI_CMD_RESET);
1424
1425         /* Version register (= 0x01) */
1426         mddi_host_reg_out(VERSION, 0x0001);
1427
1428         /* Bytes per subframe register */
1429         mddi_host_reg_out(BPS, MDDI_HOST_BYTES_PER_SUBFRAME);
1430
1431         /* Subframes per media frames register (= 0x03) */
1432         mddi_host_reg_out(SPM, 0x0003);
1433
1434         /* Turn Around 1 register (= 0x05) */
1435         mddi_host_reg_out(TA1_LEN, 0x0005);
1436
1437         /* Turn Around 2 register (= 0x0C) */
1438         mddi_host_reg_out(TA2_LEN, MDDI_HOST_TA2_LEN);
1439
1440         /* Drive hi register (= 0x96) */
1441         mddi_host_reg_out(DRIVE_HI, 0x0096);
1442
1443         /* Drive lo register (= 0x32) */
1444         mddi_host_reg_out(DRIVE_LO, 0x0032);
1445
1446         /* Display wakeup count register (= 0x3c) */
1447         mddi_host_reg_out(DISP_WAKE, 0x003c);
1448
1449         /* Reverse Rate Divisor register (= 0x2) */
1450         mddi_host_reg_out(REV_RATE_DIV, MDDI_HOST_REV_RATE_DIV);
1451
1452 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1453         /* Reverse Pointer Size */
1454         mddi_host_reg_out(REV_SIZE, MDDI_REV_BUFFER_SIZE);
1455
1456         /* Rev Encap Size */
1457         mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
1458 #endif
1459
1460         /* Periodic Rev Encap */
1461         /* don't send periodically */
1462         mddi_host_reg_out(CMD, MDDI_CMD_PERIODIC_REV_ENCAP);
1463
1464         pad_reg_val = mddi_host_reg_in(PAD_CTL);
1465         if (pad_reg_val == 0) {
1466                 /* If we are turning on band gap, need to wait 5us before turning
1467                  * on the rest of the PAD */
1468                 mddi_host_reg_out(PAD_CTL, 0x08000);
1469                 udelay(5);
1470         }
1471 #ifdef T_MSM7200
1472         /* Recommendation from PAD hw team */
1473         mddi_host_reg_out(PAD_CTL, 0xa850a);
1474 #else
1475         /* Recommendation from PAD hw team */
1476         mddi_host_reg_out(PAD_CTL, 0xa850f);
1477 #endif
1478
1479 #if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP40)
1480         mddi_host_reg_out(PAD_IO_CTL, 0x00320000);
1481         mddi_host_reg_out(PAD_CAL, 0x00220020);
1482 #endif
1483
1484         mddi_host_core_version = mddi_host_reg_inm(CORE_VER, 0xffff);
1485
1486 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1487         if (mddi_host_core_version >= 8)
1488                 mddi_rev_ptr_workaround = FALSE;
1489         pmhctl->rev_ptr_curr = pmhctl->rev_ptr_start;
1490 #endif
1491
1492         if ((mddi_host_core_version > 8) && (mddi_host_core_version < 0x19))
1493                 mddi_host_reg_out(TEST, 0x2);
1494
1495         /* Need an even number for counts */
1496         mddi_host_reg_out(DRIVER_START_CNT, 0x60006);
1497
1498 #ifndef T_MSM7500
1499         /* Setup defaults for MDP related register */
1500         mddi_host_reg_out(MDP_VID_FMT_DES, 0x5666);
1501         mddi_host_reg_out(MDP_VID_PIX_ATTR, 0x00C3);
1502         mddi_host_reg_out(MDP_VID_CLIENTID, 0);
1503 #endif
1504
1505         /* automatically hibernate after 1 empty subframe */
1506         if (pmhctl->disable_hibernation)
1507                 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
1508         else
1509                 mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
1510
1511         /* Bring up link if display (client) requests it */
1512 #ifdef MDDI_HOST_DISP_LISTEN
1513         mddi_host_reg_out(CMD, MDDI_CMD_DISP_LISTEN);
1514 #else
1515         mddi_host_reg_out(CMD, MDDI_CMD_DISP_IGNORE);
1516 #endif
1517
1518 }
1519
1520 void mddi_host_configure_interrupts(mddi_host_type host_idx, boolean enable)
1521 {
1522         unsigned long flags;
1523         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1524
1525         spin_lock_irqsave(&mddi_host_spin_lock, flags);
1526
1527         /* turn on HCLK to MDDI host core if it has been disabled */
1528         mddi_host_enable_hclk();
1529         /* Clear MDDI Interrupt enable reg */
1530         mddi_host_reg_out(INTEN, 0);
1531
1532         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1533
1534         if (enable) {
1535                 pmhctl->driver_state = MDDI_DRIVER_ENABLED;
1536
1537                 if (host_idx == MDDI_HOST_PRIM) {
1538                         if (request_irq
1539                             (INT_MDDI_PRI, mddi_pmdh_isr_proxy, IRQF_DISABLED,
1540                              "PMDH", 0) != 0)
1541                                 printk(KERN_ERR
1542                                        "a mddi: unable to request_irq\n");
1543                         else
1544                                 int_mddi_pri_flag = TRUE;
1545                 } else {
1546                         if (request_irq
1547                             (INT_MDDI_EXT, mddi_emdh_isr_proxy, IRQF_DISABLED,
1548                              "EMDH", 0) != 0)
1549                                 printk(KERN_ERR
1550                                        "b mddi: unable to request_irq\n");
1551                         else
1552                                 int_mddi_ext_flag = TRUE;
1553                 }
1554
1555                 /* Set MDDI Interrupt enable reg -- Enable Reverse data avail */
1556 #ifdef FEATURE_MDDI_DISABLE_REVERSE
1557                 mddi_host_reg_out(INTEN,
1558                                   MDDI_INT_ERROR_CONDITIONS |
1559                                   MDDI_INT_LINK_STATE_CHANGES);
1560 #else
1561                 /* Reverse Pointer register */
1562                 pmhctl->rev_ptr_written = FALSE;
1563
1564                 mddi_host_reg_out(INTEN,
1565                                   MDDI_INT_REV_DATA_AVAIL |
1566                                   MDDI_INT_ERROR_CONDITIONS |
1567                                   MDDI_INT_LINK_STATE_CHANGES);
1568                 pmhctl->rtd_counter = mddi_rtd_frequency;
1569                 pmhctl->client_status_cnt = 0;
1570 #endif
1571         } else {
1572                 if (pmhctl->driver_state == MDDI_DRIVER_ENABLED)
1573                         pmhctl->driver_state = MDDI_DRIVER_DISABLED;
1574         }
1575
1576 }
1577
1578 static void mddi_host_powerup(mddi_host_type host_idx)
1579 {
1580         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1581
1582         if (pmhctl->link_state != MDDI_LINK_DISABLED)
1583                 return;
1584
1585         /* enable IO_CLK and hclk to MDDI host core */
1586         mddi_host_enable_io_clock();
1587
1588         mddi_host_initialize_registers(host_idx);
1589         mddi_host_configure_interrupts(host_idx, TRUE);
1590
1591         pmhctl->link_state = MDDI_LINK_ACTIVATING;
1592
1593         /* Link activate command */
1594         mddi_host_reg_out(CMD, MDDI_CMD_LINK_ACTIVE);
1595
1596 #ifdef CLKRGM_MDDI_IO_CLOCK_IN_MHZ
1597         MDDI_MSG_NOTICE("MDDI Host: Activating Link %d Mbps\n",
1598                         CLKRGM_MDDI_IO_CLOCK_IN_MHZ * 2);
1599 #else
1600         MDDI_MSG_NOTICE("MDDI Host: Activating Link\n");
1601 #endif
1602
1603         /* Initialize the timer */
1604         if (host_idx == MDDI_HOST_PRIM)
1605                 mddi_host_timer_service(0);
1606 }
1607
1608 void mddi_host_init(mddi_host_type host_idx)
1609 /* Write out the MDDI configuration registers */
1610 {
1611         static boolean initialized = FALSE;
1612         mddi_host_cntl_type *pmhctl;
1613
1614         if (host_idx >= MDDI_NUM_HOST_CORES) {
1615                 MDDI_MSG_ERR("Invalid host core index\n");
1616                 return;
1617         }
1618
1619         if (!initialized) {
1620                 uint16 idx;
1621                 mddi_host_type host;
1622                 for (host = MDDI_HOST_PRIM; host < MDDI_NUM_HOST_CORES; host++) {
1623                         pmhctl = &(mhctl[host]);
1624                         initialized = TRUE;
1625
1626                         pmhctl->llist_ptr =
1627                             dma_alloc_coherent(NULL, MDDI_LLIST_POOL_SIZE,
1628                                                &(pmhctl->llist_dma_addr),
1629                                                GFP_KERNEL);
1630                         pmhctl->llist_dma_ptr =
1631                             (mddi_linked_list_type *) (void *)pmhctl->
1632                             llist_dma_addr;
1633 #ifdef FEATURE_MDDI_DISABLE_REVERSE
1634                         pmhctl->rev_data_buf = NULL;
1635                         if (pmhctl->llist_ptr == NULL)
1636 #else
1637                         mddi_rev_user.waiting = FALSE;
1638                         init_completion(&(mddi_rev_user.done_comp));
1639                         pmhctl->rev_data_buf =
1640                             dma_alloc_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
1641                                                &(pmhctl->rev_data_dma_addr),
1642                                                GFP_KERNEL);
1643                         if ((pmhctl->llist_ptr == NULL)
1644                             || (pmhctl->rev_data_buf == NULL))
1645 #endif
1646                         {
1647                                 MDDI_MSG_CRIT
1648                                     ("unable to alloc non-cached memory\n");
1649                         }
1650                         llist_extern[host] = pmhctl->llist_ptr;
1651                         llist_dma_extern[host] = pmhctl->llist_dma_ptr;
1652                         llist_extern_notify[host] = pmhctl->llist_notify;
1653
1654                         for (idx = 0; idx < UNASSIGNED_INDEX; idx++) {
1655                                 init_completion(&
1656                                                 (pmhctl->llist_notify[idx].
1657                                                  done_comp));
1658                         }
1659                         init_completion(&(pmhctl->mddi_llist_avail_comp));
1660                         spin_lock_init(&mddi_host_spin_lock);
1661                         pmhctl->mddi_waiting_for_llist_avail = FALSE;
1662                         pmhctl->mddi_rev_ptr_write_val =
1663                             (uint32) (void *)(pmhctl->rev_data_dma_addr);
1664                         pmhctl->rev_ptr_start = (void *)pmhctl->rev_data_buf;
1665
1666                         pmhctl->rev_pkt_size = MDDI_DEFAULT_REV_PKT_SIZE;
1667                         pmhctl->rev_state = MDDI_REV_IDLE;
1668 #ifdef IMAGE_MODEM_PROC
1669                         /* assume hibernation state is last state from APPS proc, so that
1670                          * we don't reinitialize the host core */
1671                         pmhctl->link_state = MDDI_LINK_HIBERNATING;
1672 #else
1673                         pmhctl->link_state = MDDI_LINK_DISABLED;
1674 #endif
1675                         pmhctl->driver_state = MDDI_DRIVER_DISABLED;
1676                         pmhctl->disable_hibernation = FALSE;
1677
1678                         /* initialize llist variables */
1679                         pmhctl->llist_info.transmitting_start_idx =
1680                             UNASSIGNED_INDEX;
1681                         pmhctl->llist_info.transmitting_end_idx =
1682                             UNASSIGNED_INDEX;
1683                         pmhctl->llist_info.waiting_start_idx = UNASSIGNED_INDEX;
1684                         pmhctl->llist_info.waiting_end_idx = UNASSIGNED_INDEX;
1685                         pmhctl->llist_info.reg_read_idx = UNASSIGNED_INDEX;
1686                         pmhctl->llist_info.next_free_idx =
1687                             MDDI_FIRST_DYNAMIC_LLIST_IDX;
1688                         pmhctl->llist_info.reg_read_waiting = FALSE;
1689
1690                         mddi_vsync_detect_enabled = FALSE;
1691                         mddi_gpio.polling_enabled = FALSE;
1692
1693                         pmhctl->int_type.count = 0;
1694                         pmhctl->int_type.in_count = 0;
1695                         pmhctl->int_type.disp_req_count = 0;
1696                         pmhctl->int_type.state_change_count = 0;
1697                         pmhctl->int_type.ll_done_count = 0;
1698                         pmhctl->int_type.rev_avail_count = 0;
1699                         pmhctl->int_type.error_count = 0;
1700                         pmhctl->int_type.rev_encap_count = 0;
1701                         pmhctl->int_type.llist_ptr_write_1 = 0;
1702                         pmhctl->int_type.llist_ptr_write_2 = 0;
1703
1704                         pmhctl->stats.fwd_crc_count = 0;
1705                         pmhctl->stats.rev_crc_count = 0;
1706                         pmhctl->stats.pri_underflow = 0;
1707                         pmhctl->stats.sec_underflow = 0;
1708                         pmhctl->stats.rev_overflow = 0;
1709                         pmhctl->stats.pri_overwrite = 0;
1710                         pmhctl->stats.sec_overwrite = 0;
1711                         pmhctl->stats.rev_overwrite = 0;
1712                         pmhctl->stats.dma_failure = 0;
1713                         pmhctl->stats.rtd_failure = 0;
1714                         pmhctl->stats.reg_read_failure = 0;
1715 #ifdef FEATURE_MDDI_UNDERRUN_RECOVERY
1716                         pmhctl->stats.pri_underrun_detected = 0;
1717 #endif
1718
1719                         pmhctl->log_parms.rtd_cnt = 0;
1720                         pmhctl->log_parms.rev_enc_cnt = 0;
1721                         pmhctl->log_parms.vid_cnt = 0;
1722                         pmhctl->log_parms.reg_acc_cnt = 0;
1723                         pmhctl->log_parms.cli_stat_cnt = 0;
1724                         pmhctl->log_parms.cli_cap_cnt = 0;
1725                         pmhctl->log_parms.reg_read_cnt = 0;
1726                         pmhctl->log_parms.link_active_cnt = 0;
1727                         pmhctl->log_parms.link_hibernate_cnt = 0;
1728                         pmhctl->log_parms.fwd_crc_cnt = 0;
1729                         pmhctl->log_parms.rev_crc_cnt = 0;
1730                         pmhctl->log_parms.vsync_response_cnt = 0;
1731
1732                         prev_parms[host_idx] = pmhctl->log_parms;
1733                         mddi_client_capability_pkt.packet_length = 0;
1734                 }
1735
1736 #ifndef T_MSM7500
1737                 /* tell clock driver we are user of this PLL */
1738                 MDDI_HOST_ENABLE_IO_CLOCK;
1739 #endif
1740         }
1741
1742         mddi_host_powerup(host_idx);
1743         pmhctl = &(mhctl[host_idx]);
1744 }
1745
1746 #ifdef CONFIG_FB_MSM_MDDI_AUTO_DETECT
1747 static uint32 mddi_client_id;
1748
1749 uint32 mddi_get_client_id(void)
1750 {
1751
1752 #ifndef FEATURE_MDDI_DISABLE_REVERSE
1753         mddi_host_type host_idx = MDDI_HOST_PRIM;
1754         static boolean client_detection_try = FALSE;
1755         mddi_host_cntl_type *pmhctl;
1756         unsigned long flags;
1757         uint16 saved_rev_pkt_size;
1758
1759         if (!client_detection_try) {
1760                 /* Toshiba display requires larger drive_lo value */
1761                 mddi_host_reg_out(DRIVE_LO, 0x0050);
1762
1763                 pmhctl = &(mhctl[MDDI_HOST_PRIM]);
1764
1765                 saved_rev_pkt_size = pmhctl->rev_pkt_size;
1766
1767                 /* Increase Rev Encap Size */
1768                 pmhctl->rev_pkt_size = MDDI_CLIENT_CAPABILITY_REV_PKT_SIZE;
1769                 mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
1770
1771                 /* disable hibernation temporarily */
1772                 if (!pmhctl->disable_hibernation)
1773                         mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE);
1774
1775                 mddi_rev_user.waiting = TRUE;
1776                 INIT_COMPLETION(mddi_rev_user.done_comp);
1777
1778                 spin_lock_irqsave(&mddi_host_spin_lock, flags);
1779
1780                 /* turn on clock(s), if they have been disabled */
1781                 mddi_host_enable_hclk();
1782                 mddi_host_enable_io_clock();
1783
1784                 mddi_client_capability_request = TRUE;
1785
1786                 if (pmhctl->rev_state == MDDI_REV_IDLE) {
1787                         /* attempt to send the reverse encapsulation now */
1788                         mddi_issue_reverse_encapsulation();
1789                 }
1790                 spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1791
1792                 wait_for_completion_killable(&(mddi_rev_user.done_comp));
1793
1794                 /* Set Rev Encap Size back to its original value */
1795                 pmhctl->rev_pkt_size = saved_rev_pkt_size;
1796                 mddi_host_reg_out(REV_ENCAP_SZ, pmhctl->rev_pkt_size);
1797
1798                 /* reenable auto-hibernate */
1799                 if (!pmhctl->disable_hibernation)
1800                         mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
1801
1802                 mddi_host_reg_out(DRIVE_LO, 0x0032);
1803                 client_detection_try = TRUE;
1804
1805                 mddi_client_id = (mddi_client_capability_pkt.Mfr_Name<<16) |
1806                                 mddi_client_capability_pkt.Product_Code;
1807
1808                 if (!mddi_client_id)
1809                         mddi_disable(1);
1810         }
1811
1812 #if 0
1813         switch (mddi_client_capability_pkt.Mfr_Name) {
1814         case 0x4474:
1815                 if ((mddi_client_capability_pkt.Product_Code != 0x8960) &&
1816                     (target == DISPLAY_1)) {
1817                         ret = PRISM_WVGA;
1818                 }
1819                 break;
1820
1821         case 0xD263:
1822                 if (target == DISPLAY_1)
1823                         ret = TOSHIBA_VGA_PRIM;
1824                 else if (target == DISPLAY_2)
1825                         ret = TOSHIBA_QCIF_SECD;
1826                 break;
1827
1828         case 0:
1829                 if (mddi_client_capability_pkt.Product_Code == 0x8835) {
1830                         if (target == DISPLAY_1)
1831                                 ret = SHARP_QVGA_PRIM;
1832                         else if (target == DISPLAY_2)
1833                                 ret = SHARP_128x128_SECD;
1834                 }
1835                 break;
1836
1837         default:
1838                 break;
1839         }
1840
1841         if ((!client_detection_try) && (ret != TOSHIBA_VGA_PRIM)
1842             && (ret != TOSHIBA_QCIF_SECD)) {
1843                 /* Not a Toshiba display, so change drive_lo back to default value */
1844                 mddi_host_reg_out(DRIVE_LO, 0x0032);
1845         }
1846 #endif
1847
1848 #endif
1849
1850         return mddi_client_id;
1851 }
1852 #endif
1853
1854 void mddi_host_powerdown(mddi_host_type host_idx)
1855 {
1856         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1857
1858         if (host_idx >= MDDI_NUM_HOST_CORES) {
1859                 MDDI_MSG_ERR("Invalid host core index\n");
1860                 return;
1861         }
1862
1863         if (pmhctl->driver_state == MDDI_DRIVER_RESET) {
1864                 return;
1865         }
1866
1867         if (host_idx == MDDI_HOST_PRIM) {
1868                 /* disable timer */
1869                 del_timer(&mddi_host_timer);
1870         }
1871
1872         mddi_host_configure_interrupts(host_idx, FALSE);
1873
1874         /* turn on HCLK to MDDI host core if it has been disabled */
1875         mddi_host_enable_hclk();
1876
1877         /* MDDI Reset command */
1878         mddi_host_reg_out(CMD, MDDI_CMD_RESET);
1879
1880         /* Pad Control Register */
1881         mddi_host_reg_out(PAD_CTL, 0x0);
1882
1883         /* disable IO_CLK and hclk to MDDI host core */
1884         mddi_host_disable_io_clock();
1885         mddi_host_disable_hclk();
1886
1887         pmhctl->link_state = MDDI_LINK_DISABLED;
1888         pmhctl->driver_state = MDDI_DRIVER_RESET;
1889
1890         MDDI_MSG_NOTICE("MDDI Host: Disabling Link\n");
1891
1892 }
1893
1894 uint16 mddi_get_next_free_llist_item(mddi_host_type host_idx, boolean wait)
1895 {
1896         unsigned long flags;
1897         uint16 ret_idx;
1898         boolean forced_wait = FALSE;
1899         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1900
1901         ret_idx = pmhctl->llist_info.next_free_idx;
1902
1903         pmhctl->llist_info.next_free_idx++;
1904         if (pmhctl->llist_info.next_free_idx >= MDDI_NUM_DYNAMIC_LLIST_ITEMS)
1905                 pmhctl->llist_info.next_free_idx = MDDI_FIRST_DYNAMIC_LLIST_IDX;
1906         spin_lock_irqsave(&mddi_host_spin_lock, flags);
1907         if (pmhctl->llist_notify[ret_idx].in_use) {
1908                 if (!wait) {
1909                         pmhctl->llist_info.next_free_idx = ret_idx;
1910                         ret_idx = UNASSIGNED_INDEX;
1911                 } else {
1912                         forced_wait = TRUE;
1913                         INIT_COMPLETION(pmhctl->mddi_llist_avail_comp);
1914                 }
1915         }
1916         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1917
1918         if (forced_wait) {
1919                 wait_for_completion_killable(&
1920                                                   (pmhctl->
1921                                                    mddi_llist_avail_comp));
1922                 MDDI_MSG_ERR("task waiting on mddi llist item\n");
1923         }
1924
1925         if (ret_idx != UNASSIGNED_INDEX) {
1926                 pmhctl->llist_notify[ret_idx].waiting = FALSE;
1927                 pmhctl->llist_notify[ret_idx].done_cb = NULL;
1928                 pmhctl->llist_notify[ret_idx].in_use = TRUE;
1929                 pmhctl->llist_notify[ret_idx].next_idx = UNASSIGNED_INDEX;
1930         }
1931
1932         return ret_idx;
1933 }
1934
1935 uint16 mddi_get_reg_read_llist_item(mddi_host_type host_idx, boolean wait)
1936 {
1937 #ifdef FEATURE_MDDI_DISABLE_REVERSE
1938         MDDI_MSG_CRIT("No reverse link available\n");
1939         (void)wait;
1940         return FALSE;
1941 #else
1942         unsigned long flags;
1943         uint16 ret_idx;
1944         boolean error = FALSE;
1945         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1946
1947         spin_lock_irqsave(&mddi_host_spin_lock, flags);
1948         if (pmhctl->llist_info.reg_read_idx != UNASSIGNED_INDEX) {
1949                 /* need to block here or is this an error condition? */
1950                 error = TRUE;
1951                 ret_idx = UNASSIGNED_INDEX;
1952         }
1953         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
1954
1955         if (!error) {
1956                 ret_idx = pmhctl->llist_info.reg_read_idx =
1957                     mddi_get_next_free_llist_item(host_idx, wait);
1958                 /* clear the reg_read_waiting flag */
1959                 pmhctl->llist_info.reg_read_waiting = FALSE;
1960         }
1961
1962         if (error)
1963                 MDDI_MSG_ERR("***** Reg read still in progress! ****\n");
1964         return ret_idx;
1965 #endif
1966
1967 }
1968
1969 void mddi_queue_forward_packets(uint16 first_llist_idx,
1970                                 uint16 last_llist_idx,
1971                                 boolean wait,
1972                                 mddi_llist_done_cb_type llist_done_cb,
1973                                 mddi_host_type host_idx)
1974 {
1975         unsigned long flags;
1976         mddi_linked_list_type *llist;
1977         mddi_linked_list_type *llist_dma;
1978         mddi_host_cntl_type *pmhctl = &(mhctl[host_idx]);
1979
1980         if ((first_llist_idx >= UNASSIGNED_INDEX) ||
1981             (last_llist_idx >= UNASSIGNED_INDEX)) {
1982                 MDDI_MSG_ERR("MDDI queueing invalid linked list\n");
1983                 return;
1984         }
1985
1986         if (pmhctl->link_state == MDDI_LINK_DISABLED)
1987                 MDDI_MSG_CRIT("MDDI host powered down!\n");
1988
1989         llist = pmhctl->llist_ptr;
1990         llist_dma = pmhctl->llist_dma_ptr;
1991
1992         /* clean cache so MDDI host can read data */
1993         memory_barrier();
1994
1995         pmhctl->llist_notify[last_llist_idx].waiting = wait;
1996         if (wait)
1997                 INIT_COMPLETION(pmhctl->llist_notify[last_llist_idx].done_comp);
1998         pmhctl->llist_notify[last_llist_idx].done_cb = llist_done_cb;
1999
2000         spin_lock_irqsave(&mddi_host_spin_lock, flags);
2001
2002         if ((pmhctl->llist_info.transmitting_start_idx == UNASSIGNED_INDEX) &&
2003             (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) &&
2004             (pmhctl->rev_state == MDDI_REV_IDLE)) {
2005                 /* no packets are currently transmitting */
2006 #ifndef FEATURE_MDDI_DISABLE_REVERSE
2007                 if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
2008                         /* This is the special case where the packet is a register read. */
2009                         pmhctl->rev_state = MDDI_REV_REG_READ_ISSUED;
2010                         mddi_reg_read_retry = 0;
2011                         /* mddi_rev_reg_read_attempt = 1; */
2012                 }
2013 #endif
2014                 /* assign transmitting index values */
2015                 pmhctl->llist_info.transmitting_start_idx = first_llist_idx;
2016                 pmhctl->llist_info.transmitting_end_idx = last_llist_idx;
2017
2018                 /* turn on clock(s), if they have been disabled */
2019                 mddi_host_enable_hclk();
2020                 mddi_host_enable_io_clock();
2021                 pmhctl->int_type.llist_ptr_write_1++;
2022                 /* Write to primary pointer register */
2023                 dma_coherent_pre_ops();
2024                 mddi_host_reg_out(PRI_PTR, &llist_dma[first_llist_idx]);
2025
2026                 /* enable interrupt when complete */
2027                 mddi_host_reg_outm(INTEN, MDDI_INT_PRI_LINK_LIST_DONE,
2028                                    MDDI_INT_PRI_LINK_LIST_DONE);
2029
2030         } else if (pmhctl->llist_info.waiting_start_idx == UNASSIGNED_INDEX) {
2031 #ifndef FEATURE_MDDI_DISABLE_REVERSE
2032                 if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
2033                         /*
2034                          * we have a register read to send but need to wait
2035                          * for current reverse activity to end or there are
2036                          * packets currently transmitting
2037                          */
2038                         /* mddi_rev_reg_read_attempt = 0; */
2039                         pmhctl->llist_info.reg_read_waiting = TRUE;
2040                 }
2041 #endif
2042
2043                 /* assign waiting index values */
2044                 pmhctl->llist_info.waiting_start_idx = first_llist_idx;
2045                 pmhctl->llist_info.waiting_end_idx = last_llist_idx;
2046         } else {
2047                 uint16 prev_end_idx = pmhctl->llist_info.waiting_end_idx;
2048 #ifndef FEATURE_MDDI_DISABLE_REVERSE
2049                 if (first_llist_idx == pmhctl->llist_info.reg_read_idx) {
2050                         /*
2051                          * we have a register read to send but need to wait
2052                          * for current reverse activity to end or there are
2053                          * packets currently transmitting
2054                          */
2055                         /* mddi_rev_reg_read_attempt = 0; */
2056                         pmhctl->llist_info.reg_read_waiting = TRUE;
2057                 }
2058 #endif
2059
2060                 llist = pmhctl->llist_ptr;
2061
2062                 /* clear end flag in previous last packet */
2063                 llist[prev_end_idx].link_controller_flags = 0;
2064                 pmhctl->llist_notify[prev_end_idx].next_idx = first_llist_idx;
2065
2066                 /* set the next_packet_pointer of the previous last packet */
2067                 llist[prev_end_idx].next_packet_pointer =
2068                     (void *)(&llist_dma[first_llist_idx]);
2069
2070                 /* clean cache so MDDI host can read data */
2071                 memory_barrier();
2072
2073                 /* assign new waiting last index value */
2074                 pmhctl->llist_info.waiting_end_idx = last_llist_idx;
2075         }
2076
2077         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2078
2079 }
2080
2081 void mddi_host_write_pix_attr_reg(uint32 value)
2082 {
2083         (void)value;
2084 }
2085
2086 void mddi_queue_reverse_encapsulation(boolean wait)
2087 {
2088 #ifdef FEATURE_MDDI_DISABLE_REVERSE
2089         MDDI_MSG_CRIT("No reverse link available\n");
2090         (void)wait;
2091 #else
2092         unsigned long flags;
2093         boolean error = FALSE;
2094         mddi_host_type host_idx = MDDI_HOST_PRIM;
2095         mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
2096
2097         spin_lock_irqsave(&mddi_host_spin_lock, flags);
2098
2099         /* turn on clock(s), if they have been disabled */
2100         mddi_host_enable_hclk();
2101         mddi_host_enable_io_clock();
2102
2103         if (wait) {
2104                 if (!mddi_rev_user.waiting) {
2105                         mddi_rev_user.waiting = TRUE;
2106                         INIT_COMPLETION(mddi_rev_user.done_comp);
2107                 } else
2108                         error = TRUE;
2109         }
2110         mddi_rev_encap_user_request = TRUE;
2111
2112         if (pmhctl->rev_state == MDDI_REV_IDLE) {
2113                 /* attempt to send the reverse encapsulation now */
2114                 mddi_host_type orig_host_idx = mddi_curr_host;
2115                 mddi_curr_host = host_idx;
2116                 mddi_issue_reverse_encapsulation();
2117                 mddi_curr_host = orig_host_idx;
2118         }
2119         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2120
2121         if (error) {
2122                 MDDI_MSG_ERR("Reverse Encap request already in progress\n");
2123         } else if (wait)
2124                 wait_for_completion_killable(&(mddi_rev_user.done_comp));
2125 #endif
2126 }
2127
2128 /* ISR to be executed */
2129 boolean mddi_set_rev_handler(mddi_rev_handler_type handler, uint16 pkt_type)
2130 {
2131 #ifdef FEATURE_MDDI_DISABLE_REVERSE
2132         MDDI_MSG_CRIT("No reverse link available\n");
2133         (void)handler;
2134         (void)pkt_type;
2135         return (FALSE);
2136 #else
2137         unsigned long flags;
2138         uint16 hdlr;
2139         boolean handler_set = FALSE;
2140         boolean overwrite = FALSE;
2141         mddi_host_type host_idx = MDDI_HOST_PRIM;
2142         mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
2143
2144         /* Disable interrupts */
2145         spin_lock_irqsave(&mddi_host_spin_lock, flags);
2146
2147         for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
2148                 if (mddi_rev_pkt_handler[hdlr].pkt_type == pkt_type) {
2149                         mddi_rev_pkt_handler[hdlr].handler = handler;
2150                         if (handler == NULL) {
2151                                 /* clearing handler from table */
2152                                 mddi_rev_pkt_handler[hdlr].pkt_type =
2153                                     INVALID_PKT_TYPE;
2154                                 handler_set = TRUE;
2155                                 if (pkt_type == 0x10) { /* video stream packet */
2156                                         /* ensure HCLK on to MDDI host core before register write */
2157                                         mddi_host_enable_hclk();
2158                                         /* No longer getting video, so reset rev encap size to default */
2159                                         pmhctl->rev_pkt_size =
2160                                             MDDI_DEFAULT_REV_PKT_SIZE;
2161                                         mddi_host_reg_out(REV_ENCAP_SZ,
2162                                                           pmhctl->rev_pkt_size);
2163                                 }
2164                         } else {
2165                                 /* already a handler for this packet */
2166                                 overwrite = TRUE;
2167                         }
2168                         break;
2169                 }
2170         }
2171         if ((hdlr >= MAX_MDDI_REV_HANDLERS) && (handler != NULL)) {
2172                 /* assigning new handler */
2173                 for (hdlr = 0; hdlr < MAX_MDDI_REV_HANDLERS; hdlr++) {
2174                         if (mddi_rev_pkt_handler[hdlr].pkt_type ==
2175                             INVALID_PKT_TYPE) {
2176                                 if ((pkt_type == 0x10) &&       /* video stream packet */
2177                                     (pmhctl->rev_pkt_size <
2178                                      MDDI_VIDEO_REV_PKT_SIZE)) {
2179                                         /* ensure HCLK on to MDDI host core before register write */
2180                                         mddi_host_enable_hclk();
2181                                         /* Increase Rev Encap Size */
2182                                         pmhctl->rev_pkt_size =
2183                                             MDDI_VIDEO_REV_PKT_SIZE;
2184                                         mddi_host_reg_out(REV_ENCAP_SZ,
2185                                                           pmhctl->rev_pkt_size);
2186                                 }
2187                                 mddi_rev_pkt_handler[hdlr].handler = handler;
2188                                 mddi_rev_pkt_handler[hdlr].pkt_type = pkt_type;
2189                                 handler_set = TRUE;
2190                                 break;
2191                         }
2192                 }
2193         }
2194
2195         /* Restore interrupts */
2196         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2197
2198         if (overwrite)
2199                 MDDI_MSG_ERR("Overwriting previous rev packet handler\n");
2200
2201         return handler_set;
2202
2203 #endif
2204 }                               /* mddi_set_rev_handler */
2205
2206 void mddi_host_disable_hibernation(boolean disable)
2207 {
2208         mddi_host_type host_idx = MDDI_HOST_PRIM;
2209         mddi_host_cntl_type *pmhctl = &(mhctl[MDDI_HOST_PRIM]);
2210
2211         if (disable) {
2212                 pmhctl->disable_hibernation = TRUE;
2213                 /* hibernation will be turned off by isr next time it is entered */
2214         } else {
2215                 if (pmhctl->disable_hibernation) {
2216                         unsigned long flags;
2217                         spin_lock_irqsave(&mddi_host_spin_lock, flags);
2218                         if (!MDDI_HOST_IS_HCLK_ON)
2219                                 MDDI_HOST_ENABLE_HCLK;
2220                         mddi_host_reg_out(CMD, MDDI_CMD_HIBERNATE | 1);
2221                         spin_unlock_irqrestore(&mddi_host_spin_lock, flags);
2222                         pmhctl->disable_hibernation = FALSE;
2223                 }
2224         }
2225 }
2226
2227 void mddi_mhctl_remove(mddi_host_type host_idx)
2228 {
2229         mddi_host_cntl_type *pmhctl;
2230
2231         pmhctl = &(mhctl[host_idx]);
2232
2233         dma_free_coherent(NULL, MDDI_LLIST_POOL_SIZE, (void *)pmhctl->llist_ptr,
2234                           pmhctl->llist_dma_addr);
2235
2236         dma_free_coherent(NULL, MDDI_MAX_REV_DATA_SIZE,
2237                           (void *)pmhctl->rev_data_buf,
2238                           pmhctl->rev_data_dma_addr);
2239 }