Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include "si_common.h" |
2 | #include "si_mhl_defs.h" | |
3 | #include "si_mhl_tx_api.h" | |
4 | #include "si_mhl_tx.h" | |
5 | #include "si_mhl_tx_base_drv_api.h" | |
6 | #include "si_drv_mhl_tx.h" | |
7 | #include "si_cra_cfg.h" | |
8 | #include "si_8338_regs.h" | |
9 | #include "si_cra.h" | |
10 | #include "smartbook.h" | |
11 | #include <linux/hrtimer.h> | |
12 | #include <linux/ktime.h> | |
13 | #include "si_drv_mdt_tx.h" | |
14 | #include "hdmi_drv.h" | |
15 | ||
16 | #define NUM_CBUS_EVENT_QUEUE_EVENTS 5 | |
17 | typedef struct _CBusQueue_t { | |
18 | uint8_t head; | |
19 | uint8_t tail; | |
20 | cbus_req_t queue[NUM_CBUS_EVENT_QUEUE_EVENTS]; | |
21 | } CBusQueue_t, *PCBusQueue_t; | |
22 | #define QUEUE_SIZE(x) (sizeof(x.queue)/sizeof(x.queue[0])) | |
23 | #define MAX_QUEUE_DEPTH(x) (QUEUE_SIZE(x) - 1) | |
24 | #define QUEUE_DEPTH(x) ((x.head <= x.tail)?(x.tail-x.head):(QUEUE_SIZE(x)-x.head+x.tail)) | |
25 | #define QUEUE_FULL(x) (QUEUE_DEPTH(x) >= MAX_QUEUE_DEPTH(x)) | |
26 | #define ADVANCE_QUEUE_HEAD(x) { x.head = (x.head < MAX_QUEUE_DEPTH(x))?(x.head+1):0; } | |
27 | #define ADVANCE_QUEUE_TAIL(x) { x.tail = (x.tail < MAX_QUEUE_DEPTH(x))?(x.tail+1):0; } | |
28 | #define RETREAT_QUEUE_HEAD(x) { x.head = (x.head > 0)?(x.head-1):MAX_QUEUE_DEPTH(x); } | |
29 | CBusQueue_t CBusQueue; | |
30 | ||
31 | extern uint8_t VIDEO_CAPABILITY_D_BLOCK_found; | |
32 | extern bool_t mscAbortFlag; | |
33 | ||
34 | struct hrtimer hr_timer_AbortTimer_CHK; | |
35 | ||
36 | enum hrtimer_restart timer_AbortTimer_CHK_callback(struct hrtimer *timer) | |
37 | { | |
38 | mscAbortFlag = false; | |
39 | TX_DEBUG_PRINT(("Drv: timer_AbortTimer_CHK_Expired now!!!!!!\n")); | |
40 | return HRTIMER_NORESTART; | |
41 | } | |
42 | ||
43 | ||
44 | cbus_req_t *GetNextCBusTransactionImpl(void) | |
45 | { | |
46 | if (0 == QUEUE_DEPTH(CBusQueue)) { | |
47 | return NULL; | |
48 | } else { | |
49 | cbus_req_t *retVal; | |
50 | retVal = &CBusQueue.queue[CBusQueue.head]; | |
51 | ADVANCE_QUEUE_HEAD(CBusQueue) | |
52 | return retVal; | |
53 | } | |
54 | } | |
55 | ||
56 | #ifdef ENABLE_TX_DEBUG_PRINT | |
57 | cbus_req_t *GetNextCBusTransactionWrapper(char *pszFunction) | |
58 | { | |
59 | TX_DEBUG_PRINT(("MhlTx:GetNextCBusTransaction: %s depth: %d head: %d tail: %d\n", | |
60 | pszFunction, | |
61 | (int)QUEUE_DEPTH(CBusQueue), (int)CBusQueue.head, (int)CBusQueue.tail)); | |
62 | return GetNextCBusTransactionImpl(); | |
63 | } | |
64 | ||
65 | #define GetNextCBusTransaction(func) GetNextCBusTransactionWrapper(#func) | |
66 | #else | |
67 | #define GetNextCBusTransaction(func) GetNextCBusTransactionImpl() | |
68 | #endif | |
69 | bool_t PutNextCBusTransactionImpl(cbus_req_t *pReq) | |
70 | { | |
71 | if (QUEUE_FULL(CBusQueue)) { | |
72 | return false; | |
73 | } | |
74 | CBusQueue.queue[CBusQueue.tail] = *pReq; | |
75 | ADVANCE_QUEUE_TAIL(CBusQueue) | |
76 | return true; | |
77 | } | |
78 | ||
79 | #ifdef ENABLE_TX_DEBUG_PRINT | |
80 | bool_t PutNextCBusTransactionWrapper(cbus_req_t *pReq) | |
81 | { | |
82 | bool_t retVal; | |
83 | TX_DEBUG_PRINT(("MhlTx: PutNextCBusTransaction %02X %02X %02X depth:%d head: %d tail:%d\n", | |
84 | (int)pReq->command, | |
85 | (int)((MHL_MSC_MSG == | |
86 | pReq->command) ? pReq->payload_u.msgData[0] : pReq->offsetData) | |
87 | , | |
88 | (int)((MHL_MSC_MSG == | |
89 | pReq->command) ? pReq->payload_u.msgData[1] : pReq->payload_u. | |
90 | msgData[0]) | |
91 | , (int)QUEUE_DEPTH(CBusQueue) | |
92 | , (int)CBusQueue.head, (int)CBusQueue.tail)); | |
93 | retVal = PutNextCBusTransactionImpl(pReq); | |
94 | if (!retVal) { | |
95 | TX_DEBUG_PRINT(("MhlTx: PutNextCBusTransaction queue full, when adding event %02x\n", (int)pReq->command)); | |
96 | } | |
97 | return retVal; | |
98 | } | |
99 | ||
100 | #define PutNextCBusTransaction(req) PutNextCBusTransactionWrapper(req) | |
101 | #else | |
102 | #define PutNextCBusTransaction(req) PutNextCBusTransactionImpl(req) | |
103 | #endif | |
104 | bool_t PutPriorityCBusTransactionImpl(cbus_req_t *pReq) | |
105 | { | |
106 | if (QUEUE_FULL(CBusQueue)) { | |
107 | TX_DEBUG_PRINT(("MhlTx Queque is full\n")); | |
108 | return false; | |
109 | } | |
110 | RETREAT_QUEUE_HEAD(CBusQueue) | |
111 | CBusQueue.queue[CBusQueue.head] = *pReq; | |
112 | return true; | |
113 | } | |
114 | ||
115 | #ifdef ENABLE_TX_DEBUG_PRINT | |
116 | bool_t PutPriorityCBusTransactionWrapper(cbus_req_t *pReq) | |
117 | { | |
118 | bool_t retVal; | |
119 | TX_DEBUG_PRINT(("MhlTx: PutPriorityCBusTransaction %02X %02X %02X depth:%d head: %d tail:%d\n", (int)pReq->command, (int)((MHL_MSC_MSG == pReq->command) ? pReq->payload_u.msgData[0] : pReq->offsetData) | |
120 | , | |
121 | (int)((MHL_MSC_MSG == | |
122 | pReq->command) ? pReq->payload_u.msgData[1] : pReq->payload_u. | |
123 | msgData[0]) | |
124 | , (int)QUEUE_DEPTH(CBusQueue) | |
125 | , (int)CBusQueue.head, (int)CBusQueue.tail)); | |
126 | retVal = PutPriorityCBusTransactionImpl(pReq); | |
127 | if (!retVal) { | |
128 | TX_DEBUG_PRINT(("MhlTx: PutPriorityCBusTransaction queue full, when adding event 0x%02X\n", (int)pReq->command)); | |
129 | } | |
130 | return retVal; | |
131 | } | |
132 | ||
133 | #define PutPriorityCBusTransaction(pReq) PutPriorityCBusTransactionWrapper(pReq) | |
134 | #else | |
135 | #define PutPriorityCBusTransaction(pReq) PutPriorityCBusTransactionImpl(pReq) | |
136 | #endif | |
137 | #define IncrementCBusReferenceCount(func) {mhlTxConfig.cbusReferenceCount++; TX_DEBUG_PRINT(("MhlTx:%s cbusReferenceCount:%d\n", #func, (int)mhlTxConfig.cbusReferenceCount)); } | |
138 | #define DecrementCBusReferenceCount(func) {mhlTxConfig.cbusReferenceCount--; TX_DEBUG_PRINT(("MhlTx:%s cbusReferenceCount:%d\n", #func, (int)mhlTxConfig.cbusReferenceCount)); } | |
139 | #define SetMiscFlag(func, x) { mhlTxConfig.miscFlags |= (x); TX_DEBUG_PRINT(("MhlTx:%s set %s\n", #func, #x)); } | |
140 | #define ClrMiscFlag(func, x) { mhlTxConfig.miscFlags &= ~(x); TX_DEBUG_PRINT(("MhlTx:%s clr %s\n", #func, #x)); } | |
141 | static mhlTx_config_t mhlTxConfig = { 0 }; | |
142 | ||
143 | static bool_t SiiMhlTxSetDCapRdy(void); | |
144 | static bool_t SiiMhlTxRapkSend(uint8_t rapkErrCode); | |
145 | static void MhlTxResetStates(void); | |
146 | static bool_t MhlTxSendMscMsg(uint8_t command, uint8_t cmdData); | |
147 | static void SiiMhlTxRefreshPeerDevCapEntries(void); | |
148 | static void MhlTxDriveStates(void); | |
149 | extern PLACE_IN_CODE_SEG uint8_t rcpSupportTable[]; | |
150 | extern HDMI_CABLE_TYPE MHL_Connect_type; | |
151 | extern void hdmi_state_callback(HDMI_STATE state); | |
152 | #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT | |
153 | extern void smartbook_state_callback(void); | |
154 | #endif | |
155 | ||
156 | bool_t MhlTxCBusBusy(void) | |
157 | { | |
158 | return ((QUEUE_DEPTH(CBusQueue) > 0) || SiiMhlTxDrvCBusBusy() | |
159 | || mhlTxConfig.cbusReferenceCount) ? true : false; | |
160 | } | |
161 | ||
162 | static uint8_t QualifyPathEnable(void) | |
163 | { | |
164 | uint8_t retVal = 0; | |
165 | if (MHL_STATUS_PATH_ENABLED & mhlTxConfig.status_1) { | |
166 | TX_DEBUG_PRINT(("\t\t\tMHL_STATUS_PATH_ENABLED\n")); | |
167 | retVal = 1; | |
168 | } else { | |
169 | if (0x10 == mhlTxConfig.aucDevCapCache[DEVCAP_OFFSET_MHL_VERSION]) { | |
170 | if (0x44 == mhlTxConfig.aucDevCapCache[DEVCAP_OFFSET_INT_STAT_SIZE]) { | |
171 | retVal = 1; | |
172 | TX_DEBUG_PRINT(("\t\t\tLegacy Support for MHL_STATUS_PATH_ENABLED\n")); | |
173 | } | |
174 | } | |
175 | } | |
176 | return retVal; | |
177 | } | |
178 | ||
179 | void SiiMhlTxTmdsEnable(void) | |
180 | { | |
181 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxTmdsEnable\n")); | |
182 | if (MHL_RSEN & mhlTxConfig.mhlHpdRSENflags) { | |
183 | TX_DEBUG_PRINT(("\tMHL_RSEN\n")); | |
184 | if (MHL_HPD & mhlTxConfig.mhlHpdRSENflags) { | |
185 | TX_DEBUG_PRINT(("\t\tMHL_HPD\n")); | |
186 | if (QualifyPathEnable()) { | |
187 | if (RAP_CONTENT_ON & mhlTxConfig.rapFlags) { | |
188 | TX_DEBUG_PRINT(("\t\t\t\tRAP CONTENT_ON\n")); | |
189 | SiiMhlTxDrvTmdsControl(true); | |
190 | } | |
191 | } | |
192 | } | |
193 | } | |
194 | } | |
195 | ||
196 | static bool_t SiiMhlTxSetInt(uint8_t regToWrite, uint8_t mask, uint8_t priorityLevel) | |
197 | { | |
198 | cbus_req_t req; | |
199 | bool_t retVal; | |
200 | req.retryCount = 2; | |
201 | req.command = MHL_SET_INT; | |
202 | req.offsetData = regToWrite; | |
203 | req.payload_u.msgData[0] = mask; | |
204 | if (0 == priorityLevel) { | |
205 | retVal = PutPriorityCBusTransaction(&req); | |
206 | } else { | |
207 | retVal = PutNextCBusTransaction(&req); | |
208 | } | |
209 | return retVal; | |
210 | } | |
211 | ||
212 | /* Timon: phase out this function since pdatabytes is not used anymore */ | |
213 | /* Why? cause pdatabytes is useless */ | |
214 | static bool_t SiiMhlTxDoWriteBurst(uint8_t startReg, uint8_t *pData, uint8_t length) | |
215 | { | |
216 | int i; | |
217 | if (FLAGS_WRITE_BURST_PENDING & mhlTxConfig.miscFlags) { | |
218 | cbus_req_t req; | |
219 | bool_t retVal; | |
220 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxDoWriteBurst startReg:%d length:%d\n", (int)startReg, | |
221 | (int)length)); | |
222 | req.retryCount = 1; | |
223 | req.command = MHL_WRITE_BURST; | |
224 | req.length = length; | |
225 | req.offsetData = startReg; | |
226 | /* req.payload_u.pdatabytes = pData; */ | |
227 | for (i = 0; i < length; i++) | |
228 | req.payload_u.msgData[i] = pData[i]; | |
229 | retVal = PutPriorityCBusTransaction(&req); | |
230 | ClrMiscFlag(SiiMhlTxDoWriteBurst, FLAGS_WRITE_BURST_PENDING) | |
231 | return retVal; | |
232 | } | |
233 | return false; | |
234 | } | |
235 | ||
236 | ScratchPadStatus_e SiiMhlTxRequestWriteBurst(uint8_t startReg, uint8_t length, uint8_t *pData) | |
237 | { | |
238 | ScratchPadStatus_e retVal = SCRATCHPAD_BUSY; | |
239 | if (!(MHL_FEATURE_SP_SUPPORT & mhlTxConfig.mscFeatureFlag)) { | |
240 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxRequestWriteBurst failed SCRATCHPAD_NOT_SUPPORTED\n")); | |
241 | retVal = SCRATCHPAD_NOT_SUPPORTED; | |
242 | } else { | |
243 | if ((FLAGS_SCRATCHPAD_BUSY & mhlTxConfig.miscFlags) | |
244 | || MhlTxCBusBusy() | |
245 | ) { | |
246 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxRequestWriteBurst failed FLAGS_SCRATCHPAD_BUSY\n")); | |
247 | } else { | |
248 | bool_t temp; | |
249 | uint8_t i, reg; | |
250 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxRequestWriteBurst, request sent\n")); | |
251 | for (i = 0, reg = startReg; (i < length) && (reg < SCRATCHPAD_SIZE); | |
252 | ++i, ++reg) { | |
253 | mhlTxConfig.localScratchPad[reg] = pData[i]; | |
254 | } | |
255 | temp = SiiMhlTxSetInt(MHL_RCHANGE_INT, MHL_INT_REQ_WRT, 1); | |
256 | retVal = temp ? SCRATCHPAD_SUCCESS : SCRATCHPAD_FAIL; | |
257 | } | |
258 | } | |
259 | return retVal; | |
260 | } | |
261 | ||
262 | int SiiMhlTxInitialize(uint8_t pollIntervalMs) | |
263 | { | |
264 | bool_t ret = false; | |
265 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxInitialize\n")); | |
266 | CBusQueue.head = 0; | |
267 | CBusQueue.tail = 0; | |
268 | mhlTxConfig.pollIntervalMs = pollIntervalMs; | |
269 | TX_DEBUG_PRINT(("MhlTx: HPD: %d RSEN: %d\n", | |
270 | (int)((mhlTxConfig.mhlHpdRSENflags & MHL_HPD) ? 1 : 0) | |
271 | , (int)((mhlTxConfig.mhlHpdRSENflags & MHL_RSEN) ? 1 : 0) | |
272 | )); | |
273 | MhlTxResetStates(); | |
274 | TX_DEBUG_PRINT(("MhlTx: HPD: %d RSEN: %d\n", | |
275 | (mhlTxConfig.mhlHpdRSENflags & MHL_HPD) ? 1 : 0, | |
276 | (mhlTxConfig.mhlHpdRSENflags & MHL_RSEN) ? 1 : 0)); | |
277 | hrtimer_init(&hr_timer_AbortTimer_CHK, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
278 | ||
279 | hr_timer_AbortTimer_CHK.function = &timer_AbortTimer_CHK_callback; | |
280 | ret = SiiMhlTxChipInitialize(); | |
281 | /* SiiInitExtVideo(); */ | |
282 | if (ret) { | |
283 | return 0; /* success */ | |
284 | } else { | |
285 | return -1; /* fail */ | |
286 | } | |
287 | } | |
288 | ||
289 | void MhlTxProcessEvents(void) | |
290 | { | |
291 | MhlTxDriveStates(); | |
292 | if (mhlTxConfig.mhlConnectionEvent) { | |
293 | TX_DEBUG_PRINT(("MhlTx:MhlTxProcessEvents mhlConnectionEvent\n")); | |
294 | mhlTxConfig.mhlConnectionEvent = false; | |
295 | AppNotifyMhlEvent(mhlTxConfig.mhlConnected, mhlTxConfig.mscFeatureFlag); | |
296 | if (MHL_TX_EVENT_DISCONNECTION == mhlTxConfig.mhlConnected) { | |
297 | MhlTxResetStates(); | |
298 | } else if (MHL_TX_EVENT_CONNECTION == mhlTxConfig.mhlConnected) { | |
299 | SiiMhlTxSetDCapRdy(); | |
300 | } | |
301 | } else if (mhlTxConfig.mscMsgArrived) { | |
302 | TX_DEBUG_PRINT(("MhlTx:MhlTxProcessEvents MSC MSG <%02X, %02X>\n", | |
303 | (int)(mhlTxConfig.mscMsgSubCommand) | |
304 | , (int)(mhlTxConfig.mscMsgData) | |
305 | )); | |
306 | mhlTxConfig.mscMsgArrived = false; | |
307 | switch (mhlTxConfig.mscMsgSubCommand) { | |
308 | case MHL_MSC_MSG_RAP: | |
309 | if (MHL_RAP_CONTENT_ON == mhlTxConfig.mscMsgData) { | |
310 | mhlTxConfig.rapFlags |= RAP_CONTENT_ON; | |
311 | TX_DEBUG_PRINT(("RAP CONTENT_ON\n")); | |
312 | SiiMhlTxTmdsEnable(); | |
313 | SiiMhlTxRapkSend(MHL_MSC_MSG_RAP_NO_ERROR); | |
314 | } else if (MHL_RAP_CONTENT_OFF == mhlTxConfig.mscMsgData) { | |
315 | mhlTxConfig.rapFlags &= ~RAP_CONTENT_ON; | |
316 | TX_DEBUG_PRINT(("RAP CONTENT_OFF\n")); | |
317 | SiiMhlTxDrvTmdsControl(false); | |
318 | SiiMhlTxRapkSend(MHL_MSC_MSG_RAP_NO_ERROR); | |
319 | } else if (MHL_RAP_CMD_POLL == mhlTxConfig.mscMsgData) { | |
320 | SiiMhlTxRapkSend(MHL_MSC_MSG_RAP_UNSUPPORTED_ACT_CODE); | |
321 | } else { | |
322 | SiiMhlTxRapkSend(MHL_MSC_MSG_RAP_UNRECOGNIZED_ACT_CODE); | |
323 | } | |
324 | break; | |
325 | case MHL_MSC_MSG_RCP: | |
326 | if (MHL_LOGICAL_DEVICE_MAP & rcpSupportTable[mhlTxConfig.mscMsgData & 0x7F]) { | |
327 | AppNotifyMhlEvent(MHL_TX_EVENT_RCP_RECEIVED, | |
328 | mhlTxConfig.mscMsgData); | |
329 | } else { | |
330 | mhlTxConfig.mscSaveRcpKeyCode = mhlTxConfig.mscMsgData; | |
331 | SiiMhlTxRcpeSend(RCPE_INEEFECTIVE_KEY_CODE); | |
332 | } | |
333 | break; | |
334 | case MHL_MSC_MSG_RCPK: | |
335 | AppNotifyMhlEvent(MHL_TX_EVENT_RCPK_RECEIVED, mhlTxConfig.mscMsgData); | |
336 | DecrementCBusReferenceCount(MhlTxProcessEvents) | |
337 | mhlTxConfig.mscLastCommand = 0; | |
338 | mhlTxConfig.mscMsgLastCommand = 0; | |
339 | TX_DEBUG_PRINT(("MhlTx:MhlTxProcessEvents RCPK\n")); | |
340 | break; | |
341 | case MHL_MSC_MSG_RCPE: | |
342 | AppNotifyMhlEvent(MHL_TX_EVENT_RCPE_RECEIVED, mhlTxConfig.mscMsgData); | |
343 | break; | |
344 | case MHL_MSC_MSG_RAPK: | |
345 | DecrementCBusReferenceCount(MhlTxProcessEvents) | |
346 | mhlTxConfig.mscLastCommand = 0; | |
347 | mhlTxConfig.mscMsgLastCommand = 0; | |
348 | TX_DEBUG_PRINT(("MhlTx:MhlTxProcessEventsRAPK\n")); | |
349 | break; | |
350 | default: | |
351 | break; | |
352 | } | |
353 | } | |
354 | } | |
355 | ||
356 | extern bool_t mscAbortFlag; | |
357 | static void MhlTxDriveStates(void) | |
358 | { | |
359 | #ifndef __KERNEL__ | |
360 | if (mscAbortFlag) { | |
361 | if (HalTimerExpired(TIMER_ABORT)) { | |
362 | mscAbortFlag = false; | |
363 | TX_DEBUG_PRINT(("Timer Tabort_next timeout!\n")); | |
364 | } else { | |
365 | return; | |
366 | } | |
367 | } | |
368 | #else | |
369 | if (mscAbortFlag) { | |
370 | TX_DEBUG_PRINT(("Abort Timer is working!\n")); | |
371 | return; | |
372 | } else { | |
373 | /* TX_DEBUG_PRINT(("normal work!\n")); */ | |
374 | } | |
375 | #endif | |
376 | if (QUEUE_DEPTH(CBusQueue) > 0) { | |
377 | /* HalTimerWait(100); */ | |
378 | if (!SiiMhlTxDrvCBusBusy()) { | |
379 | int reQueueRequest = 0; | |
380 | cbus_req_t *pReq = GetNextCBusTransaction(MhlTxDriveStates); | |
381 | if (pReq == NULL) { | |
382 | printk("mhl_drv: GetNextCBusTransaction returns null\n"); | |
383 | return; | |
384 | } | |
385 | if (MHL_SET_INT == pReq->command) { | |
386 | if (MHL_RCHANGE_INT == pReq->offsetData) { | |
387 | if (FLAGS_SCRATCHPAD_BUSY & mhlTxConfig.miscFlags) { | |
388 | if (MHL_INT_REQ_WRT == pReq->payload_u.msgData[0]) { | |
389 | reQueueRequest = 1; | |
390 | } else if (MHL_INT_GRT_WRT == | |
391 | pReq->payload_u.msgData[0]) { | |
392 | reQueueRequest = 0; | |
393 | } | |
394 | } else { | |
395 | if (MHL_INT_REQ_WRT == pReq->payload_u.msgData[0]) { | |
396 | IncrementCBusReferenceCount | |
397 | (MhlTxDriveStates) | |
398 | SetMiscFlag(MhlTxDriveStates, | |
399 | FLAGS_SCRATCHPAD_BUSY) | |
400 | SetMiscFlag(MhlTxDriveStates, | |
401 | FLAGS_WRITE_BURST_PENDING) | |
402 | } else if (MHL_INT_GRT_WRT == | |
403 | pReq->payload_u.msgData[0]) { | |
404 | SetMiscFlag(MhlTxDriveStates, | |
405 | FLAGS_SCRATCHPAD_BUSY) | |
406 | } | |
407 | } | |
408 | } | |
409 | } | |
410 | if (reQueueRequest) { | |
411 | if (pReq->retryCount-- > 0) { | |
412 | PutNextCBusTransaction(pReq); | |
413 | } | |
414 | } else { | |
415 | if (MHL_MSC_MSG == pReq->command) { | |
416 | mhlTxConfig.mscMsgLastCommand = pReq->payload_u.msgData[0]; | |
417 | mhlTxConfig.mscMsgLastData = pReq->payload_u.msgData[1]; | |
418 | } else { | |
419 | mhlTxConfig.mscLastOffset = pReq->offsetData; | |
420 | mhlTxConfig.mscLastData = pReq->payload_u.msgData[0]; | |
421 | } | |
422 | mhlTxConfig.mscLastCommand = pReq->command; | |
423 | IncrementCBusReferenceCount(MhlTxDriveStates) | |
424 | SiiMhlTxDrvSendCbusCommand(pReq); | |
425 | } | |
426 | } else { | |
427 | /* TX_DEBUG_PRINT(("SiiMhlTxDrvCBusBusy\n")); */ | |
428 | } | |
429 | } | |
430 | } | |
431 | ||
432 | static void ExamineLocalAndPeerVidLinkMode(void) | |
433 | { | |
434 | mhlTxConfig.linkMode &= ~MHL_STATUS_CLK_MODE_MASK; | |
435 | mhlTxConfig.linkMode |= MHL_STATUS_CLK_MODE_NORMAL; | |
436 | if (MHL_DEV_VID_LINK_SUPP_PPIXEL & mhlTxConfig.aucDevCapCache[DEVCAP_OFFSET_VID_LINK_MODE]) { | |
437 | if (MHL_DEV_VID_LINK_SUPP_PPIXEL & DEVCAP_VAL_VID_LINK_MODE) { | |
438 | mhlTxConfig.linkMode &= ~MHL_STATUS_CLK_MODE_MASK; | |
439 | mhlTxConfig.linkMode |= mhlTxConfig.preferredClkMode; | |
440 | } | |
441 | } | |
442 | SiMhlTxDrvSetClkMode(mhlTxConfig.linkMode & MHL_STATUS_CLK_MODE_MASK); | |
443 | } | |
444 | ||
445 | #define FLAG_OR_NOT(x) (FLAGS_HAVE_##x & mhlTxConfig.miscFlags)?#x:"" | |
446 | #define SENT_OR_NOT(x) (FLAGS_SENT_##x & mhlTxConfig.miscFlags)?#x:"" | |
447 | void SiiMhlTxMscCommandDone(uint8_t data1) | |
448 | { | |
449 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone. data1 = %02X\n", (int)data1)); | |
450 | DecrementCBusReferenceCount(SiiMhlTxMscCommandDone) | |
451 | if (MHL_READ_DEVCAP == mhlTxConfig.mscLastCommand) { | |
452 | if (mhlTxConfig.mscLastOffset < sizeof(mhlTxConfig.aucDevCapCache)) { | |
453 | mhlTxConfig.aucDevCapCache[mhlTxConfig.mscLastOffset] = data1; | |
454 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone peer DEV_CAP[0x%02x]:0x%02x index:0x%02x\n", (int)mhlTxConfig.mscLastOffset, (int)data1, (int)mhlTxConfig.ucDevCapCacheIndex)); | |
455 | if (MHL_DEV_CATEGORY_OFFSET == mhlTxConfig.mscLastOffset) { | |
456 | uint8_t param; | |
457 | mhlTxConfig.miscFlags |= FLAGS_HAVE_DEV_CATEGORY; | |
458 | param = data1 & MHL_DEV_CATEGORY_POW_BIT; | |
459 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone FLAGS_HAVE_DEV_CATEGORY\n")); | |
460 | if (MHL_TX_EVENT_STATUS_PASSTHROUGH == | |
461 | AppNotifyMhlEvent(MHL_TX_EVENT_POW_BIT_CHG, param)) { | |
462 | SiiMhlTxDrvPowBitChange((bool_t) param); | |
463 | } | |
464 | } else if (MHL_DEV_FEATURE_FLAG_OFFSET == mhlTxConfig.mscLastOffset) { | |
465 | mhlTxConfig.miscFlags |= FLAGS_HAVE_DEV_FEATURE_FLAGS; | |
466 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone FLAGS_HAVE_DEV_FEATURE_FLAGS\n")); | |
467 | mhlTxConfig.mscFeatureFlag = data1; | |
468 | TX_DEBUG_PRINT(("MhlTx: Peer's Feature Flag = %02X\n\n", | |
469 | (int)data1)); | |
470 | } else if (DEVCAP_OFFSET_VID_LINK_MODE == mhlTxConfig.mscLastOffset) { | |
471 | ExamineLocalAndPeerVidLinkMode(); | |
472 | } else if (DEVCAP_OFFSET_RESERVED == mhlTxConfig.mscLastOffset) { | |
473 | MHL_Connect_type = MHL_CABLE; | |
474 | if (mhlTxConfig.aucDevCapCache[DEVCAP_OFFSET_RESERVED] == 0xB9) { | |
475 | MHL_Connect_type = MHL_SMB_CABLE; | |
476 | } | |
477 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone connect type %d %x\n", | |
478 | MHL_Connect_type, | |
479 | mhlTxConfig. | |
480 | aucDevCapCache[DEVCAP_OFFSET_RESERVED])); | |
481 | #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT | |
482 | smartbook_state_callback(); | |
483 | if (MHL_Connect_type == MHL_SMB_CABLE) { | |
484 | SiiHidSuspend(1); /* call register input device when smartbook plug-in */ | |
485 | } | |
486 | #endif | |
487 | ||
488 | } | |
489 | ||
490 | if (++mhlTxConfig.ucDevCapCacheIndex < sizeof(mhlTxConfig.aucDevCapCache)) { | |
491 | SiiMhlTxReadDevcap(mhlTxConfig.ucDevCapCacheIndex); | |
492 | } else { | |
493 | AppNotifyMhlEvent(MHL_TX_EVENT_DCAP_CHG, 0); | |
494 | mhlTxConfig.mscLastCommand = 0; | |
495 | mhlTxConfig.mscLastOffset = 0; | |
496 | } | |
497 | } | |
498 | } else if (MHL_WRITE_STAT == mhlTxConfig.mscLastCommand) { | |
499 | TX_DEBUG_PRINT(("MhlTx: WRITE_STAT miscFlags: %02X\n\n", | |
500 | (int)mhlTxConfig.miscFlags)); | |
501 | if (MHL_STATUS_REG_CONNECTED_RDY == mhlTxConfig.mscLastOffset) { | |
502 | if (MHL_STATUS_DCAP_RDY & mhlTxConfig.mscLastData) { | |
503 | mhlTxConfig.miscFlags |= FLAGS_SENT_DCAP_RDY; | |
504 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone FLAGS_SENT_DCAP_RDY\n")); | |
505 | SiiMhlTxSetInt(MHL_RCHANGE_INT, MHL_INT_DCAP_CHG, 0); | |
506 | } | |
507 | } else if (MHL_STATUS_REG_LINK_MODE == mhlTxConfig.mscLastOffset) { | |
508 | if (MHL_STATUS_PATH_ENABLED & mhlTxConfig.mscLastData) { | |
509 | mhlTxConfig.miscFlags |= FLAGS_SENT_PATH_EN; | |
510 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone FLAGS_SENT_PATH_EN\n")); | |
511 | } | |
512 | } | |
513 | mhlTxConfig.mscLastCommand = 0; | |
514 | mhlTxConfig.mscLastOffset = 0; | |
515 | } else if (MHL_MSC_MSG == mhlTxConfig.mscLastCommand) { | |
516 | if (MHL_MSC_MSG_RCPE == mhlTxConfig.mscMsgLastCommand) { | |
517 | if (SiiMhlTxRcpkSend(mhlTxConfig.mscSaveRcpKeyCode)) { | |
518 | } | |
519 | } else { | |
520 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone default\n" | |
521 | "\tmscLastCommand: 0x%02X\n" | |
522 | "\tmscMsgLastCommand: 0x%02X mscMsgLastData: 0x%02X\n" | |
523 | "\tcbusReferenceCount: %d\n", | |
524 | (int)mhlTxConfig.mscLastCommand, | |
525 | (int)mhlTxConfig.mscMsgLastCommand, | |
526 | (int)mhlTxConfig.mscMsgLastData, | |
527 | (int)mhlTxConfig.cbusReferenceCount)); | |
528 | } | |
529 | mhlTxConfig.mscLastCommand = 0; | |
530 | } else if (MHL_WRITE_BURST == mhlTxConfig.mscLastCommand) { | |
531 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone MHL_WRITE_BURST\n")); | |
532 | mhlTxConfig.mscLastCommand = 0; | |
533 | mhlTxConfig.mscLastOffset = 0; | |
534 | mhlTxConfig.mscLastData = 0; | |
535 | /* SiiMhlTxSetInt( MHL_RCHANGE_INT,MHL_INT_DSCR_CHG,0 ); */ | |
536 | } else if (MHL_SET_INT == mhlTxConfig.mscLastCommand) { | |
537 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone MHL_SET_INT\n")); | |
538 | if (MHL_RCHANGE_INT == mhlTxConfig.mscLastOffset) { | |
539 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone MHL_RCHANGE_INT\n")); | |
540 | if (MHL_INT_DSCR_CHG == mhlTxConfig.mscLastData) { | |
541 | DecrementCBusReferenceCount(SiiMhlTxMscCommandDone) | |
542 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone MHL_INT_DSCR_CHG\n")); | |
543 | ClrMiscFlag(SiiMhlTxMscCommandDone, FLAGS_SCRATCHPAD_BUSY) | |
544 | } | |
545 | } | |
546 | mhlTxConfig.mscLastCommand = 0; | |
547 | mhlTxConfig.mscLastOffset = 0; | |
548 | mhlTxConfig.mscLastData = 0; | |
549 | } else { | |
550 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone default\n" | |
551 | "\tmscLastCommand: 0x%02X mscLastOffset: 0x%02X\n" | |
552 | "\tcbusReferenceCount: %d\n", (int)mhlTxConfig.mscLastCommand, | |
553 | (int)mhlTxConfig.mscLastOffset, | |
554 | (int)mhlTxConfig.cbusReferenceCount)); | |
555 | } | |
556 | if (!(FLAGS_RCP_READY & mhlTxConfig.miscFlags)) { | |
557 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscCommandDone. have(%s %s) sent(%s %s)\n", | |
558 | FLAG_OR_NOT(DEV_CATEGORY) | |
559 | , FLAG_OR_NOT(DEV_FEATURE_FLAGS) | |
560 | , SENT_OR_NOT(PATH_EN) | |
561 | , SENT_OR_NOT(DCAP_RDY) | |
562 | )); | |
563 | if (FLAGS_HAVE_DEV_CATEGORY & mhlTxConfig.miscFlags) { | |
564 | if (FLAGS_HAVE_DEV_FEATURE_FLAGS & mhlTxConfig.miscFlags) { | |
565 | if (FLAGS_SENT_PATH_EN & mhlTxConfig.miscFlags) { | |
566 | if (FLAGS_SENT_DCAP_RDY & mhlTxConfig.miscFlags) { | |
567 | if (mhlTxConfig.ucDevCapCacheIndex >= | |
568 | sizeof(mhlTxConfig.aucDevCapCache)) { | |
569 | mhlTxConfig.miscFlags |= FLAGS_RCP_READY; | |
570 | mhlTxConfig.mhlConnectionEvent = true; | |
571 | mhlTxConfig.mhlConnected = | |
572 | MHL_TX_EVENT_RCP_READY; | |
573 | AppNotifyMhlEvent(mhlTxConfig.mhlConnected, | |
574 | 0); | |
575 | } | |
576 | } | |
577 | } | |
578 | } | |
579 | } | |
580 | } | |
581 | } | |
582 | ||
583 | #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT | |
584 | int SiiHidWrite(int key); | |
585 | #endif | |
586 | void SiiMhlTxMscWriteBurstDone(uint8_t data1) | |
587 | { | |
588 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscWriteBurstDone(%02X)\n", (int)data1)); | |
589 | #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT | |
590 | SiiHidWrite(0); | |
591 | #else | |
592 | #define WRITE_BURST_TEST_SIZE 16 | |
593 | uint8_t temp[WRITE_BURST_TEST_SIZE]; | |
594 | uint8_t i; | |
595 | data1 = data1; | |
596 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxMscWriteBurstDone(%02X) \"", (int)data1)); | |
597 | SiiMhlTxDrvGetScratchPad(0, temp, WRITE_BURST_TEST_SIZE); | |
598 | for (i = 0; i < WRITE_BURST_TEST_SIZE; ++i) { | |
599 | if (temp[i] >= ' ') { | |
600 | TX_DEBUG_PRINT(("%02X %c ", (int)temp[i], temp[i])); | |
601 | } else { | |
602 | TX_DEBUG_PRINT(("%02X . ", (int)temp[i])); | |
603 | } | |
604 | } | |
605 | TX_DEBUG_PRINT(("\"\n")); | |
606 | #endif | |
607 | } | |
608 | ||
609 | void SiiMhlTxGotMhlMscMsg(uint8_t subCommand, uint8_t cmdData) | |
610 | { | |
611 | mhlTxConfig.mscMsgArrived = true; | |
612 | mhlTxConfig.mscMsgSubCommand = subCommand; | |
613 | mhlTxConfig.mscMsgData = cmdData; | |
614 | } | |
615 | ||
616 | ||
617 | #ifdef MDT_SUPPORT | |
618 | extern enum mdt_state g_state_for_mdt; | |
619 | extern struct msc_request g_prior_msc_request; | |
620 | #endif | |
621 | ||
622 | ||
623 | ||
624 | /* extern enum mdt_state g_state_for_mdt; */ | |
625 | void SiiMhlTxGotMhlIntr(uint8_t intr_0, uint8_t intr_1) | |
626 | { | |
627 | TX_DEBUG_PRINT(("MhlTx: INTERRUPT Arrived. %02X, %02X\n", (int)intr_0, (int)intr_1)); | |
628 | if (MHL_INT_DCAP_CHG & intr_0) { | |
629 | if (MHL_STATUS_DCAP_RDY & mhlTxConfig.status_0) { | |
630 | SiiMhlTxRefreshPeerDevCapEntries(); | |
631 | } | |
632 | } | |
633 | if (MHL_INT_DSCR_CHG & intr_0) { | |
634 | SiiMhlTxDrvGetScratchPad(0, mhlTxConfig.localScratchPad, | |
635 | sizeof(mhlTxConfig.localScratchPad)); | |
636 | ClrMiscFlag(SiiMhlTxGotMhlIntr, FLAGS_SCRATCHPAD_BUSY) | |
637 | AppNotifyMhlEvent(MHL_TX_EVENT_DSCR_CHG, 0); | |
638 | } | |
639 | #ifdef MDT_SUPPORT | |
640 | /* /////////////////////// */ | |
641 | if ((g_state_for_mdt != WAIT_FOR_WRITE_BURST_COMPLETE) | |
642 | && (g_state_for_mdt != WAIT_FOR_REQ_WRT) | |
643 | && (g_state_for_mdt != WAIT_FOR_GRT_WRT_COMPLETE)) | |
644 | #endif | |
645 | { | |
646 | ||
647 | if (MHL_INT_REQ_WRT & intr_0) { | |
648 | if (FLAGS_SCRATCHPAD_BUSY & mhlTxConfig.miscFlags) { | |
649 | SiiMhlTxSetInt(MHL_RCHANGE_INT, MHL_INT_GRT_WRT, 1); | |
650 | } else { | |
651 | SetMiscFlag(SiiMhlTxGotMhlIntr, FLAGS_SCRATCHPAD_BUSY) | |
652 | SiiMhlTxSetInt(MHL_RCHANGE_INT, MHL_INT_GRT_WRT, 0); | |
653 | } | |
654 | } | |
655 | } /* ///////////////////// */ | |
656 | if (MHL_INT_GRT_WRT & intr_0) { | |
657 | uint8_t length = sizeof(mhlTxConfig.localScratchPad); | |
658 | TX_DEBUG_PRINT(("MhlTx: MHL_INT_GRT_WRT length:%d\n", (int)length)); | |
659 | SiiMhlTxDoWriteBurst(0x40, mhlTxConfig.localScratchPad, length); | |
660 | } | |
661 | if (MHL_INT_EDID_CHG & intr_1) { | |
662 | SiiMhlTxDrvNotifyEdidChange(); | |
663 | } | |
664 | } | |
665 | ||
666 | void SiiMhlTxGotMhlStatus(uint8_t status_0, uint8_t status_1) | |
667 | { | |
668 | uint8_t StatusChangeBitMask0, StatusChangeBitMask1; | |
669 | StatusChangeBitMask0 = status_0 ^ mhlTxConfig.status_0; | |
670 | StatusChangeBitMask1 = status_1 ^ mhlTxConfig.status_1; | |
671 | mhlTxConfig.status_0 = status_0; | |
672 | mhlTxConfig.status_1 = status_1; | |
673 | if (MHL_STATUS_DCAP_RDY & StatusChangeBitMask0) { | |
674 | TX_DEBUG_PRINT(("MhlTx: DCAP_RDY changed\n")); | |
675 | if (MHL_STATUS_DCAP_RDY & status_0) { | |
676 | SiiMhlTxRefreshPeerDevCapEntries(); | |
677 | } | |
678 | } | |
679 | if (MHL_STATUS_PATH_ENABLED & StatusChangeBitMask1) { | |
680 | TX_DEBUG_PRINT(("MhlTx: PATH_EN changed\n")); | |
681 | if (MHL_STATUS_PATH_ENABLED & status_1) { | |
682 | SiiMhlTxSetPathEn(); | |
683 | } else { | |
684 | SiiMhlTxClrPathEn(); | |
685 | } | |
686 | } | |
687 | } | |
688 | ||
689 | bool_t SiiMhlTxRcpSend(uint8_t rcpKeyCode) | |
690 | { | |
691 | bool_t retVal; | |
692 | if ((0 == (MHL_FEATURE_RCP_SUPPORT & mhlTxConfig.mscFeatureFlag)) | |
693 | || !(FLAGS_RCP_READY & mhlTxConfig.miscFlags) | |
694 | ) { | |
695 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxRcpSend failed\n")); | |
696 | retVal = false; | |
697 | } | |
698 | retVal = MhlTxSendMscMsg(MHL_MSC_MSG_RCP, rcpKeyCode); | |
699 | if (retVal) { | |
700 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxRcpSend\n")); | |
701 | IncrementCBusReferenceCount(SiiMhlTxRcpSend) | |
702 | MhlTxDriveStates(); | |
703 | } | |
704 | return retVal; | |
705 | } | |
706 | ||
707 | bool_t SiiMhlTxRcpkSend(uint8_t rcpKeyCode) | |
708 | { | |
709 | bool_t retVal; | |
710 | retVal = MhlTxSendMscMsg(MHL_MSC_MSG_RCPK, rcpKeyCode); | |
711 | if (retVal) { | |
712 | MhlTxDriveStates(); | |
713 | } | |
714 | return retVal; | |
715 | } | |
716 | ||
717 | static bool_t SiiMhlTxRapkSend(uint8_t rapkErrCode) | |
718 | { | |
719 | bool_t retVal; | |
720 | retVal = MhlTxSendMscMsg(MHL_MSC_MSG_RAPK, rapkErrCode); | |
721 | if (retVal) { | |
722 | MhlTxDriveStates(); | |
723 | } | |
724 | return retVal; | |
725 | } | |
726 | ||
727 | bool_t SiiMhlTxRcpeSend(uint8_t rcpeErrorCode) | |
728 | { | |
729 | bool_t retVal; | |
730 | retVal = MhlTxSendMscMsg(MHL_MSC_MSG_RCPE, rcpeErrorCode); | |
731 | if (retVal) { | |
732 | MhlTxDriveStates(); | |
733 | } | |
734 | return retVal; | |
735 | } | |
736 | ||
737 | static bool_t SiiMhlTxSetStatus(uint8_t regToWrite, uint8_t value) | |
738 | { | |
739 | cbus_req_t req; | |
740 | bool_t retVal; | |
741 | req.retryCount = 2; | |
742 | req.command = MHL_WRITE_STAT; | |
743 | req.offsetData = regToWrite; | |
744 | req.payload_u.msgData[0] = value; | |
745 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxSetStatus\n")); | |
746 | retVal = PutNextCBusTransaction(&req); | |
747 | return retVal; | |
748 | } | |
749 | ||
750 | static bool_t SiiMhlTxSetDCapRdy(void) | |
751 | { | |
752 | mhlTxConfig.connectedReady |= MHL_STATUS_DCAP_RDY; | |
753 | return SiiMhlTxSetStatus(MHL_STATUS_REG_CONNECTED_RDY, mhlTxConfig.connectedReady); | |
754 | } | |
755 | ||
756 | static bool_t SiiMhlTxSendLinkMode(void) | |
757 | { | |
758 | return SiiMhlTxSetStatus(MHL_STATUS_REG_LINK_MODE, mhlTxConfig.linkMode); | |
759 | } | |
760 | ||
761 | bool_t SiiMhlTxSetPathEn(void) | |
762 | { | |
763 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxSetPathEn\n")); | |
764 | SiiMhlTxTmdsEnable(); | |
765 | mhlTxConfig.linkMode |= MHL_STATUS_PATH_ENABLED; | |
766 | return SiiMhlTxSetStatus(MHL_STATUS_REG_LINK_MODE, mhlTxConfig.linkMode); | |
767 | } | |
768 | ||
769 | bool_t SiiMhlTxClrPathEn(void) | |
770 | { | |
771 | TX_DEBUG_PRINT(("MhlTx: SiiMhlTxClrPathEn\n")); | |
772 | SiiMhlTxDrvTmdsControl(false); | |
773 | mhlTxConfig.linkMode &= ~MHL_STATUS_PATH_ENABLED; | |
774 | return SiiMhlTxSetStatus(MHL_STATUS_REG_LINK_MODE, mhlTxConfig.linkMode); | |
775 | } | |
776 | ||
777 | bool_t SiiMhlTxReadDevcap(uint8_t offset) | |
778 | { | |
779 | cbus_req_t req; | |
780 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxReadDevcap\n")); | |
781 | req.retryCount = 2; | |
782 | req.command = MHL_READ_DEVCAP; | |
783 | req.offsetData = offset; | |
784 | req.payload_u.msgData[0] = 0; | |
785 | return PutNextCBusTransaction(&req); | |
786 | } | |
787 | ||
788 | static void SiiMhlTxRefreshPeerDevCapEntries(void) | |
789 | { | |
790 | if (mhlTxConfig.ucDevCapCacheIndex >= sizeof(mhlTxConfig.aucDevCapCache)) { | |
791 | mhlTxConfig.ucDevCapCacheIndex = 0; | |
792 | SiiMhlTxReadDevcap(mhlTxConfig.ucDevCapCacheIndex); | |
793 | } | |
794 | } | |
795 | ||
796 | static bool_t MhlTxSendMscMsg(uint8_t command, uint8_t cmdData) | |
797 | { | |
798 | cbus_req_t req; | |
799 | uint8_t ccode; | |
800 | req.retryCount = 2; | |
801 | req.command = MHL_MSC_MSG; | |
802 | req.payload_u.msgData[0] = command; | |
803 | req.payload_u.msgData[1] = cmdData; | |
804 | ccode = PutNextCBusTransaction(&req); | |
805 | return ((bool_t) ccode); | |
806 | } | |
807 | ||
808 | void SiiMhlTxNotifyConnection(bool_t mhlConnected) | |
809 | { | |
810 | mhlTxConfig.mhlConnectionEvent = true; | |
811 | TX_DEBUG_PRINT(("MhlTx: SiiMhlTxNotifyConnection MSC_STATE_IDLE %01X\n", | |
812 | (int)mhlConnected)); | |
813 | if (mhlConnected) { | |
814 | ||
815 | ||
816 | ||
817 | mhlTxConfig.rapFlags |= RAP_CONTENT_ON; | |
818 | TX_DEBUG_PRINT(("RAP CONTENT_ON\n")); | |
819 | mhlTxConfig.mhlConnected = MHL_TX_EVENT_CONNECTION; | |
820 | mhlTxConfig.mhlHpdRSENflags |= MHL_RSEN; | |
821 | SiiMhlTxTmdsEnable(); | |
822 | SiiMhlTxSendLinkMode(); | |
823 | } else { | |
824 | ||
825 | ||
826 | mhlTxConfig.rapFlags &= ~RAP_CONTENT_ON; | |
827 | TX_DEBUG_PRINT(("RAP CONTENT_OFF\n")); | |
828 | mhlTxConfig.mhlConnected = MHL_TX_EVENT_DISCONNECTION; | |
829 | mhlTxConfig.mhlHpdRSENflags &= ~MHL_RSEN; | |
830 | } | |
831 | MhlTxProcessEvents(); | |
832 | } | |
833 | ||
834 | extern uint8_t prefertiming; | |
835 | void SiiMhlTxNotifyDsHpdChange(uint8_t dsHpdStatus) | |
836 | { | |
837 | TX_DEBUG_PRINT(("MhlTx: SiiMhlTxNotifyDsHpdChange dsHpdStatus=%d\n", (int)dsHpdStatus)); | |
838 | if (mscAbortFlag) { | |
839 | TX_DEBUG_PRINT(("Abort Timer is working in SiiMhlTxNotifyDsHpdChange!\n")); | |
840 | return; | |
841 | } | |
842 | ||
843 | if (0 == dsHpdStatus) { | |
844 | TX_DEBUG_PRINT(("MhlTx: Disable TMDS\n")); | |
845 | TX_DEBUG_PRINT(("MhlTx: DsHPD OFF\n")); | |
846 | mhlTxConfig.mhlHpdRSENflags &= ~MHL_HPD; | |
847 | AppNotifyMhlDownStreamHPDStatusChange(dsHpdStatus); | |
848 | SiiMhlTxDrvTmdsControl(false); | |
849 | hdmi_state_callback(HDMI_STATE_NO_DEVICE); | |
850 | #ifdef CONFIG_MTK_SMARTBOOK_SUPPORT | |
851 | if (MHL_Connect_type == MHL_SMB_CABLE) | |
852 | SiiHidSuspend(0); /* kirby 20130529 */ | |
853 | #endif | |
854 | } else { | |
855 | hdmi_state_callback(HDMI_STATE_ACTIVE); | |
856 | TX_DEBUG_PRINT(("MhlTx: Enable TMDS\n")); | |
857 | TX_DEBUG_PRINT(("MhlTx: DsHPD ON\n")); | |
858 | mhlTxConfig.mhlHpdRSENflags |= MHL_HPD; | |
859 | AppNotifyMhlDownStreamHPDStatusChange(dsHpdStatus); | |
860 | /*********************************for data range test*************************/ | |
861 | /* SiiRegModify(REG_VID_ACEN, BIT1, CLEAR_BITS); */ | |
862 | /* SiiRegModify(REG_VID_MODE, BIT4, BIT4); */ | |
863 | TX_EDID_PRINT(("SiiRegRead(TX_PAGE_L0 | 0x0049)=0x%x@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n", | |
864 | SiiRegRead(TX_PAGE_L0 | 0x0049))); | |
865 | ||
866 | SiiRegWrite(TX_PAGE_L0 | 0x0049, 0x00); | |
867 | TX_EDID_PRINT(("SiiRegRead(TX_PAGE_L0 | 0x0049)=0x%x################################\n", SiiRegRead(TX_PAGE_L0 | 0x0049))); | |
868 | /*********************************for data range test*************************/ | |
869 | SiiDrvMhlTxReadEdid(); | |
870 | if (VIDEO_CAPABILITY_D_BLOCK_found == true) { | |
871 | /* you should set the Quantization Ranges to limited range here(16-235). */ | |
872 | SiiRegWrite(TX_PAGE_L0 | 0x0049, BIT3 | BIT5 | BIT7); | |
873 | TX_EDID_PRINT(("SiiRegRead(TX_PAGE_L0 | 0x0049)=0x%x&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\n", SiiRegRead(TX_PAGE_L0 | 0x0049))); | |
874 | } | |
875 | ||
876 | siHdmiTx_VideoSel(prefertiming); /* setting the VIC and AVI info */ | |
877 | /* here you should set the prefer timing. */ | |
878 | ||
879 | SiiMhlTxTmdsEnable(); | |
880 | } | |
881 | } | |
882 | ||
883 | static void MhlTxResetStates(void) | |
884 | { | |
885 | mhlTxConfig.mhlConnectionEvent = false; | |
886 | mhlTxConfig.mhlConnected = MHL_TX_EVENT_DISCONNECTION; | |
887 | mhlTxConfig.mhlHpdRSENflags &= ~(MHL_RSEN | MHL_HPD); | |
888 | mhlTxConfig.rapFlags &= ~RAP_CONTENT_ON; | |
889 | TX_DEBUG_PRINT(("RAP CONTENT_OFF\n")); | |
890 | mhlTxConfig.mscMsgArrived = false; | |
891 | mhlTxConfig.status_0 = 0; | |
892 | mhlTxConfig.status_1 = 0; | |
893 | mhlTxConfig.connectedReady = 0; | |
894 | mhlTxConfig.linkMode = MHL_STATUS_CLK_MODE_NORMAL; | |
895 | mhlTxConfig.preferredClkMode = MHL_STATUS_CLK_MODE_NORMAL; | |
896 | mhlTxConfig.cbusReferenceCount = 0; | |
897 | mhlTxConfig.miscFlags = 0; | |
898 | mhlTxConfig.mscLastCommand = 0; | |
899 | mhlTxConfig.mscMsgLastCommand = 0; | |
900 | mhlTxConfig.ucDevCapCacheIndex = 1 + sizeof(mhlTxConfig.aucDevCapCache); | |
901 | } | |
902 | ||
903 | uint8_t SiiTxReadConnectionStatus(void) | |
904 | { | |
905 | return (mhlTxConfig.mhlConnected >= MHL_TX_EVENT_RCP_READY) ? 1 : 0; | |
906 | } | |
907 | ||
908 | uint8_t SiiMhlTxSetPreferredPixelFormat(uint8_t clkMode) | |
909 | { | |
910 | if (~MHL_STATUS_CLK_MODE_MASK & clkMode) { | |
911 | return 1; | |
912 | } else { | |
913 | mhlTxConfig.preferredClkMode = clkMode; | |
914 | if (mhlTxConfig.ucDevCapCacheIndex <= sizeof(mhlTxConfig.aucDevCapCache)) { | |
915 | if (mhlTxConfig.ucDevCapCacheIndex > DEVCAP_OFFSET_VID_LINK_MODE) { | |
916 | ExamineLocalAndPeerVidLinkMode(); | |
917 | } | |
918 | } | |
919 | return 0; | |
920 | } | |
921 | } | |
922 | ||
923 | uint8_t SiiTxGetPeerDevCapEntry(uint8_t index, uint8_t *pData) | |
924 | { | |
925 | if (mhlTxConfig.ucDevCapCacheIndex < sizeof(mhlTxConfig.aucDevCapCache)) { | |
926 | return 1; | |
927 | } else { | |
928 | *pData = mhlTxConfig.aucDevCapCache[index]; | |
929 | return 0; | |
930 | } | |
931 | } | |
932 | ||
933 | ScratchPadStatus_e SiiGetScratchPadVector(uint8_t offset, uint8_t length, uint8_t *pData) | |
934 | { | |
935 | if (!(MHL_FEATURE_SP_SUPPORT & mhlTxConfig.mscFeatureFlag)) { | |
936 | TX_DEBUG_PRINT(("MhlTx:SiiMhlTxRequestWriteBurst failed SCRATCHPAD_NOT_SUPPORTED\n")); | |
937 | return SCRATCHPAD_NOT_SUPPORTED; | |
938 | } else if (FLAGS_SCRATCHPAD_BUSY & mhlTxConfig.miscFlags) { | |
939 | return SCRATCHPAD_BUSY; | |
940 | } else if ((offset >= sizeof(mhlTxConfig.localScratchPad)) || | |
941 | (length > (sizeof(mhlTxConfig.localScratchPad) - offset))) { | |
942 | return SCRATCHPAD_BAD_PARAM; | |
943 | } else { | |
944 | uint8_t i, reg; | |
945 | for (i = 0, reg = offset; | |
946 | (i < length) && (reg < sizeof(mhlTxConfig.localScratchPad)); ++i, ++reg) { | |
947 | pData[i] = mhlTxConfig.localScratchPad[reg]; | |
948 | } | |
949 | return SCRATCHPAD_SUCCESS; | |
950 | } | |
951 | } | |
952 | ||
953 | void SiiMhlTxNotifyRgndMhl(void) | |
954 | { | |
955 | if (MHL_TX_EVENT_STATUS_PASSTHROUGH == AppNotifyMhlEvent(MHL_TX_EVENT_RGND_MHL, 0)) { | |
956 | /* SiiMhlTxDrvProcessRgndMhl(); */ | |
957 | } | |
958 | } | |
959 | ||
960 | /* ///////////////////////////////////////////////////////////////////////////// */ | |
961 | /* */ | |
962 | /* CBusQueueReset */ | |
963 | /* */ | |
964 | void CBusQueueReset(void) | |
965 | { | |
966 | TX_DEBUG_PRINT(("MhlTx:CBusQueueReset\n")); | |
967 | ||
968 | /* reset queue of pending CBUS requests. */ | |
969 | CBusQueue.head = 0; | |
970 | CBusQueue.tail = 0; | |
971 | /* QUEUE_DEPTH(CBusQueue)=0; */ | |
972 | } | |
973 | ||
974 | ||
975 | #if defined(__KERNEL__) && defined(USE_PROC) | |
976 | void mhl_seq_show(struct seq_file *s) | |
977 | { | |
978 | if (mhlTxConfig.mhlHpdRSENflags & MHL_HPD) | |
979 | seq_puts(s, "MHL CABLE CONNECTED [YES]\n"); | |
980 | else | |
981 | seq_puts(s, "MHL CABLE CONNECTED [NO]\n"); | |
982 | if (mhlTxConfig.mhlHpdRSENflags & MHL_RSEN) | |
983 | seq_puts(s, "MHL SOURCE CONNECTED [YES]\n"); | |
984 | else | |
985 | seq_puts(s, "MHL SOURCE CONNECTED [NO]\n"); | |
986 | if (mhlTxConfig.connectedReady & MHL_STATUS_DCAP_RDY) | |
987 | seq_puts(s, "MHL DCP_RDY [YES]\n"); | |
988 | else | |
989 | seq_puts(s, "MHL DCP_RDY [NO]\n"); | |
990 | seq_printf(s, "Work Queque Depth: [%d]\n", (int)QUEUE_DEPTH(CBusQueue)); | |
991 | } | |
992 | #endif |