1 /***************************************************************************
5 * SiI9244 - MHL Transmitter Driver
9 * Copyright (C) (2011, Silicon Image Inc)
13 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation version 2.
21 * This program is distributed ¡°as is¡± WITHOUT ANY WARRANTY of any
23 * kind, whether express or implied; without even the implied warranty
25 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
31 *****************************************************************************/
33 #include <linux/interrupt.h>
34 #include <linux/irq.h>
35 #include <linux/i2c.h>
36 #include <linux/gpio.h>
39 #include <linux/delay.h>
40 #include <plat/gpio-cfg.h>
41 #include <mach/regs-gpio.h>
42 #include <mach/regs-clock.h>
44 #include <linux/syscalls.h>
45 #include <linux/fcntl.h>
46 #include <asm/uaccess.h>
47 #include <linux/types.h>
49 #include "Common_Def.h"
50 #include "si_apiCbus.h"
52 //extern void rcp_cbus_uevent(void); //MHL v1 //NAGSM_Android_SEL_Kernel_Aakash_20101126
55 //------------------------------------------------------------------------------
57 //------------------------------------------------------------------------------
61 byte rcpKeyCode; //!< RCP CBUS Key Code
63 } SI_Rc5RcpConversion_t;
65 SI_Rc5RcpConversion_t RcpSourceToSink[] =
67 { MHD_RCP_CMD_SELECT, "Select"},
68 { MHD_RCP_CMD_UP, "Up"},
69 { MHD_RCP_CMD_DOWN, "Down"},
70 { MHD_RCP_CMD_LEFT, "Left"},
71 { MHD_RCP_CMD_RIGHT, "Right"},
72 //{ MHD_RCP_CMD_RIGHT_UP, "Right Up"},
73 //{ MHD_RCP_CMD_RIGHT_DOWN, "Right Down"},
74 //{ MHD_RCP_CMD_LEFT_UP, "Left Up"},
75 //{ MHD_RCP_CMD_LEFT_DOWN, "Left Down"},
76 { MHD_RCP_CMD_ROOT_MENU, "Root Menu"},
77 //{ MHD_RCP_CMD_SETUP_MENU, "Setup Menu"},
78 //{ MHD_RCP_CMD_CONTENTS_MENU, "Contents Menu"},
79 //{ MHD_RCP_CMD_FAVORITE_MENU, "Favorite Menu"},
80 { MHD_RCP_CMD_EXIT, "Exit"},
81 // 0x0E - 0x1F Reserved
82 { MHD_RCP_CMD_NUM_0, "Num 0"},
83 { MHD_RCP_CMD_NUM_1, "Num 1"},
84 { MHD_RCP_CMD_NUM_2, "Num 2"},
85 { MHD_RCP_CMD_NUM_3, "Num 3"},
86 { MHD_RCP_CMD_NUM_4, "Num 4"},
87 { MHD_RCP_CMD_NUM_5, "Num 5"},
88 { MHD_RCP_CMD_NUM_6, "Num 6"},
89 { MHD_RCP_CMD_NUM_7, "Num 7"},
90 { MHD_RCP_CMD_NUM_8, "Num 8"},
91 { MHD_RCP_CMD_NUM_9, "Num 9"},
92 //{ MHD_RCP_CMD_DOT, "Dot"},
93 { MHD_RCP_CMD_ENTER, "Enter"},
94 { MHD_RCP_CMD_CLEAR, "Clear"},
95 // 0x2D - 0x2F Reserved
96 { MHD_RCP_CMD_CH_UP, "Channel Up"},
97 { MHD_RCP_CMD_CH_DOWN, "Channel Down"},
98 { MHD_RCP_CMD_PRE_CH, "Previous Channel"},
99 { MHD_RCP_CMD_SOUND_SELECT, "Sound Select"},
100 //{ MHD_RCP_CMD_INPUT_SELECT, "Input Select"},
101 //{ MHD_RCP_CMD_SHOW_INFO, "Show Info"},
102 //{ MHD_RCP_CMD_HELP, "Help"},
103 //{ MHD_RCP_CMD_PAGE_UP, "Page Up"},
104 //{ MHD_RCP_CMD_PAGE_DOWN, "Page Down"},
105 // 0x39 - 0x40 Reserved
106 { MHD_RCP_CMD_VOL_UP, "Volume Up"},
107 { MHD_RCP_CMD_VOL_DOWN, "Volume Down"},
108 { MHD_RCP_CMD_MUTE, "Mute"},
109 { MHD_RCP_CMD_PLAY, "Play"},
110 { MHD_RCP_CMD_STOP, "Stop"},
111 { MHD_RCP_CMD_PAUSE, "Pause"},
112 { MHD_RCP_CMD_RECORD, "Record"},
113 { MHD_RCP_CMD_REWIND, "Rewind"},
114 { MHD_RCP_CMD_FAST_FWD, "Fast Fwd"},
115 { MHD_RCP_CMD_EJECT, "Eject"},
116 { MHD_RCP_CMD_FWD, "Forward"},
117 { MHD_RCP_CMD_BKWD, "Backward"},
118 // 0X4D - 0x4F Reserved
119 //{ MHD_RCP_CMD_ANGLE, "Angle"},
120 //{ MHD_RCP_CMD_SUBPICTURE, "Subpicture"},
121 // 0x52 - 0x5F Reserved
122 { MHD_RCP_CMD_PLAY_FUNC, "Play Function"},
123 { MHD_RCP_CMD_PAUSE_PLAY_FUNC, "Pause Play Function"},
124 { MHD_RCP_CMD_RECORD_FUNC, "Record Function"},
125 { MHD_RCP_CMD_PAUSE_REC_FUNC, "Pause Record Function"},
126 { MHD_RCP_CMD_STOP_FUNC, "Stop Function"},
127 { MHD_RCP_CMD_MUTE_FUNC, "Mute Function"},
128 { MHD_RCP_CMD_UN_MUTE_FUNC, "Un-Mute Function"},
129 //{ MHD_RCP_CMD_TUNE_FUNC, "Tune Function"},
130 //{ MHD_RCP_CMD_MEDIA_FUNC, "Media Function"},
131 // 0x69 - 0x70 Reserved
132 //{ MHD_RCP_CMD_F1, "F1"},
133 //{ MHD_RCP_CMD_F2, "F2"},
134 //{ MHD_RCP_CMD_F3, "F3"},
135 //{ MHD_RCP_CMD_F4, "F4"},
136 //{ MHD_RCP_CMD_F5, "F5"},
137 // 0x76 - 0x7D Reserved
138 //{ MHD_RCP_CMD_VS, "Vendor Specific"}
142 //------------------------------------------------------------------------------
143 // Function: CbusRc5toRcpConvert
144 // Description: Translate RC5 command to CBUS RCP command
145 // Parameters: keyData: key code from the remote controller
146 // Returns: RCP code equivalent to passed RC5 key code or 0xFF if not in list.
147 //------------------------------------------------------------------------------
149 static byte CbusRc5toRcpConvert ( byte keyCode )
153 byte length = sizeof(RcpSourceToSink)/sizeof(SI_Rc5RcpConversion_t);
155 for ( i = 0; i < length ; i++ )
157 if ( keyCode == RcpSourceToSink[i].rcpKeyCode )
159 retVal = RcpSourceToSink[i].rcpKeyCode;
161 printk("CPCBUS:: Send ----> %s\n",
162 RcpSourceToSink[i].rcpName );
168 /* Return the new code or 0xFF if not found. */
170 return( ( i == length ) ? 0xFF : retVal );
173 //------------------------------------------------------------------------------
174 // Function: CpCbusSendRcpMessage
175 // Description: Convert input port number to CBUS channel and send the
176 // passed RC5 key code as a CBUS RCP key code.
177 // Parameters: port - Port Processor input port index
178 // keyCode - Remote control button code.
179 // Returns: true if successful, false if not MHD port or other failure.
180 //------------------------------------------------------------------------------
182 Bool CpCbusSendRcpMessage ( byte channel, byte keyCode )
189 printk( "CPCBUS:: Sending RCP Msg:: %02X keycode"
190 " to channel %d CBUS\n\n",
191 (int)keyCode, (int)channel );
192 if (channel == 0xFF) {
193 printk( "\n::::::: Bad channel -- " );
197 keyCode = CbusRc5toRcpConvert( keyCode );
198 if (keyCode == 0xFF) {
199 printk( "\n::::::: Bad KeyCode -- " );
203 success = SI_CbusMscMsgSubCmdSend( channel,
211 printk("Unable to send command :::::::\n");
217 //------------------------------------------------------------------------------
218 // Function: CpCbusSendRapMessage
219 // Parameters: port - Port Processor input port index
220 // actionCode - Action code.
221 // Returns: true if successful, false if not MHD port or other failure.
222 //------------------------------------------------------------------------------
224 Bool CpCbusSendRapMessage ( byte channel, byte actCode )
231 printk( "CPCBUS:: Sending RAP Msg:: %02X action code"
232 " to channel %d CBUS\n\n",
233 (int)actCode, (int)channel );
235 if ( channel == 0xFF) {
236 printk("\n::::::: Bad channel -- ");
240 if ((actCode == MHD_RAP_CMD_POLL) ||
241 (actCode == MHD_RAP_CMD_CHG_QUIET) ||
242 (actCode != MHD_RAP_CMD_CHG_ACTIVE_PWR)) {
243 success = SI_CbusMscMsgSubCmdSend(channel,
248 printk("\n::::::: Bad action code -- ");
254 printk( "Unable to send action command :::::::\n" );
260 //------------------------------------------------------------------------------
261 // Function: CpProcessRcpMessage
262 // Description: Process the passed RCP message.
263 // Returns: The RCPK status code.
264 //------------------------------------------------------------------------------
266 static byte CpProcessRcpMessage ( byte channel, byte rcpData )
268 byte rcpkStatus = MHD_MSC_MSG_NO_ERROR;
270 printk("RCP Key Code: 0x%02X, channel: 0x%02X\n",
271 (int)rcpData, (int)channel );
274 case MHD_RCP_CMD_SELECT:
275 printk("\nSelect received\n\n");
278 printk("\nUp received\n\n");
280 case MHD_RCP_CMD_DOWN:
281 printk("\nDown received\n\n");
283 case MHD_RCP_CMD_LEFT:
284 printk("\nLeft received\n\n");
286 case MHD_RCP_CMD_RIGHT:
287 printk("\nRight received\n\n");
289 case MHD_RCP_CMD_RIGHT_UP:
290 printk("\n MHD_RCP_CMD_RIGHT_UP\n\n");
292 case MHD_RCP_CMD_RIGHT_DOWN:
293 printk("\n MHD_RCP_CMD_RIGHT_DOWN \n\n");
295 case MHD_RCP_CMD_LEFT_UP:
296 printk("\n MHD_RCP_CMD_LEFT_UP\n\n");
298 case MHD_RCP_CMD_LEFT_DOWN:
299 printk("\n MHD_RCP_CMD_LEFT_DOWN\n\n");
301 case MHD_RCP_CMD_ROOT_MENU:
302 printk("\nRoot Menu received\n\n");
304 case MHD_RCP_CMD_SETUP_MENU:
305 printk("\n MHD_RCP_CMD_SETUP_MENU\n\n");
308 case MHD_RCP_CMD_CONTENTS_MENU:
309 printk("\n MHD_RCP_CMD_CONTENTS_MENU\n\n");
312 case MHD_RCP_CMD_FAVORITE_MENU:
313 printk("\n MHD_RCP_CMD_FAVORITE_MENU\n\n");
316 case MHD_RCP_CMD_EXIT:
317 printk("\nExit received\n\n");
320 case MHD_RCP_CMD_NUM_0:
321 printk("\nNumber 0 received\n\n");
324 case MHD_RCP_CMD_NUM_1:
325 printk("\nNumber 1 received\n\n");
328 case MHD_RCP_CMD_NUM_2:
329 printk("\nNumber 2 received\n\n");
332 case MHD_RCP_CMD_NUM_3:
333 printk("\nNumber 3 received\n\n");
336 case MHD_RCP_CMD_NUM_4:
337 printk("\nNumber 4 received\n\n");
340 case MHD_RCP_CMD_NUM_5:
341 printk("\nNumber 5 received\n\n");
344 case MHD_RCP_CMD_NUM_6:
345 printk("\nNumber 6 received\n\n");
348 case MHD_RCP_CMD_NUM_7:
349 printk("\nNumber 7 received\n\n");
352 case MHD_RCP_CMD_NUM_8:
353 printk("\nNumber 8 received\n\n");
356 case MHD_RCP_CMD_NUM_9:
357 printk("\nNumber 9 received\n\n");
360 case MHD_RCP_CMD_DOT:
361 printk("\n MHD_RCP_CMD_DOT\n\n");
364 case MHD_RCP_CMD_ENTER:
365 printk("\nEnter received\n\n");
368 case MHD_RCP_CMD_CLEAR:
369 printk("\nClear received\n\n");
372 case MHD_RCP_CMD_CH_UP:
373 printk("\n MHD_RCP_CMD_CH_UP\n\n");
376 case MHD_RCP_CMD_CH_DOWN:
377 printk("\n MHD_RCP_CMD_CH_DOWN\n\n");
380 case MHD_RCP_CMD_PRE_CH:
381 printk("\n MHD_RCP_CMD_PRE_CH\n\n");
384 case MHD_RCP_CMD_SOUND_SELECT:
385 printk("\nSound Select received\n\n");
388 case MHD_RCP_CMD_INPUT_SELECT:
389 printk("\n MHD_RCP_CMD_INPUT_SELECT\n\n");
392 case MHD_RCP_CMD_SHOW_INFO:
393 printk("\n MHD_RCP_CMD_SHOW_INFO\n\n");
396 case MHD_RCP_CMD_HELP:
397 printk("\n MHD_RCP_CMD_HELP\n\n");
400 case MHD_RCP_CMD_PAGE_UP:
401 printk("\n MHD_RCP_CMD_PAGE_UP\n\n");
404 case MHD_RCP_CMD_PAGE_DOWN:
405 printk("\n MHD_RCP_CMD_PAGE_DOWN\n\n");
408 case MHD_RCP_CMD_VOL_UP:
409 printk("\n MHD_RCP_CMD_VOL_UP\n\n");
412 case MHD_RCP_CMD_VOL_DOWN:
413 printk("\n MHD_RCP_CMD_VOL_DOWN\n\n");
416 case MHD_RCP_CMD_MUTE:
417 printk("\n MHD_RCP_CMD_MUTE\n\n");
420 case MHD_RCP_CMD_PLAY:
421 printk("\nPlay received\n\n");
424 case MHD_RCP_CMD_STOP:
425 printk("\n MHD_RCP_CMD_STOP\n\n");
428 case MHD_RCP_CMD_PAUSE:
429 printk("\nPause received\n\n");
432 case MHD_RCP_CMD_RECORD:
433 printk("\n MHD_RCP_CMD_RECORD\n\n");
436 case MHD_RCP_CMD_FAST_FWD:
437 printk("\nFastfwd received\n\n");
440 case MHD_RCP_CMD_REWIND:
441 printk("\nRewind received\n\n");
444 case MHD_RCP_CMD_EJECT:
445 printk("\nEject received\n\n");
448 case MHD_RCP_CMD_FWD:
449 printk("\nForward received\n\n");
452 case MHD_RCP_CMD_BKWD:
453 printk("\nBackward received\n\n");
456 case MHD_RCP_CMD_PLAY_FUNC:
457 printk("\nPlay Function received\n\n");
460 case MHD_RCP_CMD_PAUSE_PLAY_FUNC:
461 printk("\nPause_Play Function received\n\n");
464 case MHD_RCP_CMD_STOP_FUNC:
465 printk("\nStop Function received\n\n");
469 rcpkStatus = MHD_MSC_MSG_INEFFECTIVE_KEY_CODE;
473 if ( rcpkStatus == MHD_MSC_MSG_INEFFECTIVE_KEY_CODE ) {
474 printk("\nKeyCode not recognized or supported.\n\n");
480 //------------------------------------------------------------------------------
481 // Function: CpProcessRapMessage
482 // Description: Process the passed RAP message.
483 // Returns: The RAPK status code.
484 //------------------------------------------------------------------------------
486 static byte CpProcessRapMessage ( byte channel, byte rcpData )
488 byte rapkStatus = MHD_MSC_MSG_NO_ERROR;
490 printk("RAP Key Code: 0x%02X, channel: 0x%02X\n",
491 (int)rcpData, (int)channel );
494 case MHD_RAP_CMD_POLL:
495 printk("\nPOLL received\n\n");
498 case MHD_RAP_CMD_CHG_ACTIVE_PWR:
499 printk( "\nCHANGE TO ACTIVE POWER STATE"
503 case MHD_RAP_CMD_CHG_QUIET:
504 printk( "\nCHANGE TO QUIET STATE"
506 //TPI_GoToD3(); //???
510 rapkStatus = MHD_MSC_MSG_RAP_UNRECOGNIZED_ACT_CODE;
514 if ( rapkStatus == MHD_MSC_MSG_RAP_UNRECOGNIZED_ACT_CODE ) {
515 printk("\nKeyCode not recognized !! \n\n" );
521 //------------------------------------------------------------------------------
522 // Function: CbusConnectionCheck
523 // Description: Display any change in CBUS connection state and enable
524 // CBUS heartbeat if channel has been connected.
525 // Parameters: channel - CBUS channel to check
526 //------------------------------------------------------------------------------
528 static void CbusConnectionCheck (byte channel)
530 static byte busConnected[ MHD_MAX_CHANNELS ] = {0};
532 /* If CBUS connection state has changed for this channel, */
533 /* update channel state and hardware. */
535 if (busConnected[channel] != SI_CbusChannelConnected(channel)) {
536 busConnected[ channel ] = SI_CbusChannelConnected( channel );
538 // heartbeat has been disabled in all products
539 // SI_CbusHeartBeat( channel, busConnected[ channel ] );
541 printk("CPCBUS:: ***Channel: %d, CBUS %s ****\n",
543 busConnected[ channel ] ?
544 "Connected" : "Unconnected");
548 //------------------------------------------------------------------------------
549 // Function: CpCbusProcessPrivateMessage
550 // Description: Get the result of the last message sent and use it appropriately
551 // or process a request from the connected device.
552 // Parameters: channel - CBUS channel that has message data for us.
553 //------------------------------------------------------------------------------
555 static void CpCbusProcessPrivateMessage(byte channel)
558 cbus_req_t *pCmdRequest;
560 pCmdRequest = SI_CbusRequestData( channel );
561 //CbusRcpData = pCmdRequest->offsetData;
563 switch ( pCmdRequest->command ) {
564 case MHD_MSC_MSG_RCP:
565 printk("MHD_MSC_MSG_RCP 1 \n");
566 /* Acknowledge receipt of command and process it. Note that */
567 /* we could send the ack before processing anything, because it */
568 /* is an indicator that the command was properly received, not */
569 /* that it was executed, however, we use one function to parse */
570 /* the command for errors AND for processing. The only thing we */
571 /* must do is make sure that the processing does not exceed the */
572 /* ACK response time limit. */
575 /* NAGSM_Android_SEL_Kernel_Aakash_20101130 */
576 /* Inform Kernel only on MHD_MSC_MSG_RCP */
577 //CbusRcpData = pCmdRequest->offsetData;
580 //MHL v1 //NAGSM_Android_SEL_Kernel_Aakash_20101126
582 status = CpProcessRcpMessage(channel, pCmdRequest->offsetData);
583 SI_CbusRcpMessageAck(channel, status, pCmdRequest->offsetData);
586 case MHD_MSC_MSG_RCPK:
587 printk("MHD_MSC_MSG_RCPK 1\n");
590 case MHD_MSC_MSG_RCPE:
591 printk("MHD_MSC_MSG_RCPE 1\n");
594 case MHD_MSC_MSG_RAP:
595 printk("MHD_MSC_MSG_RAP 1\n");
596 status = CpProcessRapMessage(channel, pCmdRequest->offsetData );
597 SI_CbusRapMessageAck(channel, status);
600 case MHD_MSC_MSG_RAPK:
605 //------------------------------------------------------------------------------
606 // Function: CpCbusHandler
607 // Description: Polls the send/receive state of the CBUS hardware.
608 //------------------------------------------------------------------------------
610 void CpCbusHandler(void)
612 byte channel, status;
614 /* Monitor all CBUS channels. */
616 for (channel = 0; channel < MHD_MAX_CHANNELS; channel++) {
617 /* Update CBUS status. */
618 SI_CbusUpdateBusStatus( channel );
619 CbusConnectionCheck( channel );
621 /* Monitor CBUS interrupts. */
622 status = SI_CbusHandler( channel );
623 if ( status == STATUS_SUCCESS ) {
624 /* Get status of current request, if any. */
626 status = SI_CbusRequestStatus( channel );
629 printk("CBUS_REQ_IDLE\n");
632 case CBUS_REQ_PENDING:
633 printk("CBUS_REQ_PENDING\n");
637 printk("CBUS_REQ_SENT\n");
640 case CBUS_REQ_RECEIVED:
641 printk("CBUS_REQ_RECEIVED\n");
642 /* Received a message or message response. */
643 /* Go do what is appropriate. */
645 CpCbusProcessPrivateMessage( channel );
651 } else if ( status == ERROR_NO_HEARTBEAT ) {
652 printk("Lost CBUS channel %d heartbeat\n",
654 } else if ( status == ERROR_NACK_FROM_PEER ) {
655 printk ("NACK received from peer, cmd should be"
658 /* Lee: Only thing that comes here is interrupt timeout */
659 /* -- is this bad? */
664 //------------------------------------------------------------------------------
665 // Function: CpCbusInitialize
666 // Description: Initialize the CBUS subsystem and enabled the default channels
667 //------------------------------------------------------------------------------
669 void CpCbusInitialize(void)
671 /* Initialize the basic hardware. */