NvError NvEcPowerSuspend(
    NvEcPowerState PowerState)
{
    NvError e = NvSuccess;
    NvEcPrivState   *ec = &g_ec;

    NvOsMutexLock(ec->mutex);
    
    // Call transport's power off only if it's in ON state
    if (ec->powerState == NV_TRUE)
    {
        // Perform pre-suspend EC operations
        NV_CHECK_ERROR_CLEANUP( NvEcPrivPowerSuspendHook(ec->hEc, PowerState) );
        // Enter low power state
        ec->EnterLowPowerState = NV_TRUE;
        // Signal priv thread to get ready for power suspend.
        NvOsSemaphoreSignal(ec->sema);
        // Wait till priv thread is ready for power suspend.
        NvOsSemaphoreWait(ec->LowPowerEntrySema);
        e = NvEcTransportPowerSuspend(ec->transport);
        ec->powerState = NV_FALSE;
    }

fail:
    NvOsMutexUnlock(ec->mutex);
    return e;
}
static void PmuThread(void* args)
{
    NvRmPmu* pPmu = (NvRmPmu*)args;

    for (;;)
    {
        NvOsSemaphoreWait(pPmu->hSemaphore);
        if (pPmu->AbortThread)
        {
            break;
        }

        NvOsMutexLock(pPmu->hMutex);
        if (pPmu->IntrMasked)
        {
            NvOsMutexUnlock(pPmu->hMutex);
            continue;
        }
        NvOdmPmuInterruptHandler(pPmu->hOdmPmu);
        NvOsMutexUnlock(pPmu->hMutex);

        if (pPmu->hInterrupt)
            NvRmInterruptDone(pPmu->hInterrupt);
    }
}
/*
 * Thread to send no-op commands to EC
 */
static void
NvEcPrivPingThread(void *args)
{
	NvError NvStatus = NvError_Success;
	NvEcRequest req;
	NvEcResponse resp;
	NvEcPrivState *ec = (NvEcPrivState *)args;
//Nvidia_patch_ for_ deviceLockup_and_audio_lost_issue[START]
	//set_freezable_with_signal();
	  set_freezable();
//Nvidia_patch_ for_ deviceLockup_and_audio_lost_issue[END]


	for (;;) {
	NvOsSemaphoreWait(ec->hPingSema);
	if (ec->exitPingThread)
		break;

	// send no-op commands
	DISP_MESSAGE(("NvEcPrivPingThread: Sending no-op command\n"));
	req.PacketType = NvEcPacketType_Request;
	req.RequestType = NvEcRequestResponseType_Control;
	req.RequestSubtype = (NvEcRequestResponseSubtype)
		NvEcControlSubtype_NoOperation;
	req.NumPayloadBytes = 0;

	NvStatus = NvEcSendRequest(
			ec->hEc,
			&req,
			&resp,
			sizeof(req),
			sizeof(resp));
	if (NvStatus != NvError_Success)
	DISP_MESSAGE(("NvEcPrivPingThread: no-op command send fail\n"));

	if (resp.Status != NvEcStatus_Success)
	DISP_MESSAGE(("NvEcPrivPingThread: no-op command fail\n"));

	DISP_MESSAGE(("NvEcPrivPingThread: no-op command sent\n"));
	ec->IsEcActive = NV_FALSE;
	}
}
Beispiel #4
0
void NvBatteryEventHandlerThread(void *args)
{
	NvU8	BatteryState = 0, BatteryEvent = 0;

	for (;;) {
		NvOsSemaphoreWait(batt_dev->hOdmSemaphore);

		if (batt_dev->exitThread)
			break;

		if (!batt_dev->hOdmBattDev)
			continue;

		NvOdmBatteryGetBatteryStatus(batt_dev->hOdmBattDev,
			NvOdmBatteryInst_Main,
			&BatteryState);

		NvOdmBatteryGetEvent(batt_dev->hOdmBattDev, &BatteryEvent);
NvOsDebugPrintf("ec_rs BatteryEvent = 0x%x\n", BatteryEvent);
		if ((BatteryState == NVODM_BATTERY_STATUS_UNKNOWN) ||
			(BatteryEvent == NvOdmBatteryEventType_Num)) {
			/* Do nothing */
		} else {
			//if (BatteryEvent & NvOdmBatteryEventType_RemainingCapacityAlarm) {
			if (BatteryEvent & NvOdmBatteryEventType_LowBatteryIntr) {
				//Daniel 20100701, just force off while receive LOW_BAT# interrupt(not low capacity alarm).
				//if (BatteryState == (NVODM_BATTERY_STATUS_CRITICAL |
				//	NVODM_BATTERY_STATUS_VERY_CRITICAL |
				//	NVODM_BATTERY_STATUS_DISCHARGING)) {
				//	pr_info("nvec_battery:calling kernel_power_off...\n");
NvOsDebugPrintf("ec_rs batt low battery interrupt.\r\n");
				//	kernel_power_off();
				//}
			} else {
				/* Update the battery and power supply info for other events */
				power_supply_changed(&tegra_power_supplies[NvPowerSupply_TypeBattery]);
				power_supply_changed(&tegra_power_supplies[NvPowerSupply_TypeAC]);
			}
		}
	}
}
NvError
NvEcSendRequest(
    NvEcHandle hEc,
    NvEcRequest *pRequest,
    NvEcResponse *pResponse,
    NvU32 RequestSize,
    NvU32 ResponseSize)
{
    NvEcPrivState       *ec;
    NvError             e = NvSuccess;
    NvEcRequestNode     *requestNode = NULL;
    NvEcResponseNode    *responseNode = NULL;
    NvOsSemaphoreHandle requestSema = NULL;
    NvOsSemaphoreHandle responseSema = NULL;
    
    NV_ASSERT( pRequest );
    NV_ASSERT( hEc );
    if ( (RequestSize > sizeof(NvEcRequest)) || 
         (ResponseSize > sizeof(NvEcResponse)) )
        return NvError_InvalidSize;
    
    ec = hEc->ec;
    requestNode = NvOsAlloc(sizeof(NvEcRequestNode));
    if ( NULL == requestNode )
    {
        e = NvError_InsufficientMemory;
        goto fail;
    }
    NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &requestSema, 0 ) );
    
    if ( pResponse )
    {
        responseNode = NvOsAlloc(sizeof(NvEcResponseNode));
        if ( NULL == responseNode )
        {
            e = NvError_InsufficientMemory;
            goto fail;
        }
        NV_CHECK_ERROR_CLEANUP( NvOsSemaphoreCreate( &responseSema, 0 ) );
    }

    ec->IsEcActive = NV_TRUE;

    // request end-queue.  Timeout set to infinite until request sent.
    NvOsMemset( requestNode, 0, sizeof(NvEcRequestNode) );
    pRequest->RequestorTag = hEc->tag;      // assigned tag here
    DISP_MESSAGE(("NvEcSendRequest:pRequest->RequestorTag=0x%x\n", pRequest->RequestorTag));
    NvOsMemcpy(&requestNode->request, pRequest, RequestSize);
    requestNode->tag = hEc->tag;
    DISP_MESSAGE(("NvEcSendRequest:requestNode->tag=0x%x\n", requestNode->tag));
    requestNode->sema = requestSema;
    requestNode->timeout = NV_WAIT_INFINITE;
    requestNode->completed = NV_FALSE;
    requestNode->size = RequestSize;
    
    NvOsMutexLock( ec->requestMutex );
    NVEC_ENQ( ec->request, requestNode );
    DISP_MESSAGE(("\r\nSendReq ec->requestBegin=0x%x", ec->requestBegin));
    NvOsMutexUnlock( ec->requestMutex );
    
    // response en-queue.  Timeout set to infinite until request completes.
    if ( pResponse )
    {
        NvOsMemset( responseNode, 0, sizeof(NvEcResponseNode) );
        requestNode->responseNode = responseNode;   // association between
        responseNode->requestNode = requestNode;    //   request & response
        responseNode->sema = responseSema;
        responseNode->timeout = NV_WAIT_INFINITE;
        responseNode->tag = hEc->tag;
        DISP_MESSAGE(("NvEcSendRequest:responseNode->tag=0x%x\n", responseNode->tag));
        responseNode->size = ResponseSize;
        NvOsMutexLock( ec->responseMutex );
        NVEC_ENQ( ec->response, responseNode );
        DISP_MESSAGE(("\r\nSendReq ec->responseBegin=0x%x", ec->responseBegin));
        NvOsMutexUnlock( ec->responseMutex );
    }

    NvOsMutexLock( ec->mutex );
    if ( !ec->thread )
        NvEcPrivThreadCreate( ec );
    NvOsMutexUnlock( ec->mutex );

    // Trigger EcPrivThread
    NvOsSemaphoreSignal( ec->sema );
    DISP_MESSAGE(("\r\nSendReq requestNode=0x%x, requestNode->responseNode=0x%x",
        requestNode, requestNode->responseNode));
    // Wait on Request returns
    NvOsSemaphoreWait( requestSema );
    DISP_MESSAGE(("\r\nSendReq Out of req sema"));

    e = requestNode->status;
    if ( NvSuccess != e )
    {
        NvEcResponseNode    *t = NULL, *p = NULL;

        // de-queue responseNode too !!!!
        NvOsMutexLock( ec->responseMutex );
        NVEC_REMOVE_FROM_Q( ec->response, responseNode, t, p );
        DISP_MESSAGE(("\r\nSendReq responseBegin=0x%x", ec->responseBegin));
        NvOsMutexUnlock( ec->responseMutex );
        goto fail;
    }

    if ( pResponse )
    {
        // Wait on Response returns
        NvOsSemaphoreWait( responseSema );
        DISP_MESSAGE(("\r\nSendReq Out of resp sema"));
        NV_CHECK_ERROR_CLEANUP( responseNode->status );
        NvOsMemcpy(pResponse, &responseNode->response, ResponseSize);
    }
    // if successful, nodes should be de-queue already but not freed yet

fail:
    NvOsSemaphoreDestroy( requestSema );
    NvOsSemaphoreDestroy( responseSema );
    DISP_MESSAGE(("\r\nSendReq Freeing requestNode=0x%x, responseNode=0x%x", 
        requestNode, responseNode));
    NvOsFree( requestNode );
    NvOsFree( responseNode );
    return e;
}
/*
 * Always use one EcPrivThread-global clock/time for timeout calculations
 */
static void
NvEcPrivThread( void * args )
{
    NvEcPrivState   *ec = (NvEcPrivState *)args;
    NvU32           t, timeout = NV_WAIT_INFINITE;
    NvU32           tStatus = 0;
    NvError         wait = NvSuccess;
    NvError         e;

    while( !ec->exitThread )
    {
    #if ENABLE_TIMEOUT
        if ( timeout )
            wait = NvOsSemaphoreWaitTimeout( ec->sema, timeout );
    #else
        NvOsSemaphoreWait( ec->sema );
        wait = NvSuccess;
    #endif
        
    #if ENABLE_FAKE_TIMEOUT_TEST
        t = ec->lastTime + 0x200;
    #else
        t = NvOsGetTimeMS();
    #endif
        ec->timeDiff = t - ec->lastTime;
        ec->lastTime = t;      // update last timer value
        
        if ( !timeout || (wait == NvError_Timeout) )
        {
            // timeout case
            NvEcPrivProcessTimeout( ec );
        }
        
        // look for any pending packets
        tStatus = NvEcTransportQueryStatus( ec->transport );
        
        e = NvSuccess;

        /* 
         * SEND_COMPLETE event must be processed before RESPONSE_RECEIVE_COMPLETE 
         * event as SEND_COMPLETE event schedules timeout for RESPONSE_RECEIVE event.
         */
        if ( tStatus & (NVEC_TRANSPORT_STATUS_SEND_COMPLETE |
                         NVEC_TRANSPORT_STATUS_SEND_ERROR) )
        {
            NvEcPrivProcessPostSendRequest( ec,
                (tStatus & NVEC_TRANSPORT_STATUS_SEND_COMPLETE) ?
                    NvSuccess : NvError_I2cWriteFailed );
        }

        if ( tStatus & (NVEC_TRANSPORT_STATUS_RESPONSE_RECEIVE_ERROR |
                    NVEC_TRANSPORT_STATUS_RESPONSE_RECEIVE_COMPLETE) )
        {
            e = (tStatus & NVEC_TRANSPORT_STATUS_RESPONSE_RECEIVE_COMPLETE) ?
                    NvSuccess : NvError_I2cReadFailed;
            e = NvEcPrivProcessReceiveResponse( ec, e );
            // return ignored.  Could be spurious response.
        }
        if ( tStatus & (NVEC_TRANSPORT_STATUS_EVENT_RECEIVE_ERROR |
                    NVEC_TRANSPORT_STATUS_EVENT_RECEIVE_COMPLETE) )
        {
            e = (tStatus & NVEC_TRANSPORT_STATUS_EVENT_RECEIVE_COMPLETE) ?
                    NvSuccess : NvError_I2cReadFailed;
            e = NvEcPrivProcessReceiveEvent( ec, e );
                // return ignored.  Could be spurious event.
        }

	if ( tStatus & NVEC_TRANSPORT_STATUS_EVENT_PACKET_MAX_NACK ) {
		// signal the ping thread to send a ping command since max
		// number of nacks have been sent to the EC
		if (ec->hPingSema) {
			NvOsSemaphoreSignal(ec->hPingSema);
		}
	}

        // send request whenever possible 
        if ( (ec->timeout[NVEC_IDX_REQUEST] == NV_WAIT_INFINITE) && 
             (ec->EnterLowPowerState == NV_FALSE) )
            NvEcPrivProcessSendRequest( ec );
    #if ENABLE_TIMEOUT
        timeout = NvEcPrivUpdateActualTimeout( ec ); 
    #endif
        
        if (ec->EnterLowPowerState)
        {
            // This code assumes that EC is already in kept in sleep mode by
            // either shim or top level code. And there will not be any activity
            // going on SM bus.
            if (ec->timeout[NVEC_IDX_REQUEST] != NV_WAIT_INFINITE)
            {
                NvOsDebugPrintf("\r\nNvEc has active requests during suspend. "
                    "It shouldn't have. check it.");
            }
            
            // No active request is pending. Enter into low power state.
            // Signal power suspend API to enter into suspend mode.
            NvOsSemaphoreSignal(ec->LowPowerEntrySema);
            // Wait till power resume API signals resume operation.
            NvOsSemaphoreWait(ec->LowPowerExitSema);
            // Update the timeouts for the active responses, which are scheduled 
            // to receive before system entering into suspend.
#if ENABLE_TIMEOUT
            NvEcPrivResetActiveRequestResponseTimeouts( ec );
            timeout = NvEcPrivUpdateActualTimeout( ec );
#endif // ENABLE_TIMEOUT
        }
    }
}
Beispiel #7
0
static void tegra_audiofx_notifier_thread(void *arg)
{
	struct tegra_audio_data *audio_context = (struct tegra_audio_data *)arg;
	FxNotifier *m_FxNotifier = (FxNotifier*)&audio_context->m_FxNotifier;
	NvError e;
	int retry = 0;
	NvU32 messageSize;
	NvAudioFxMessage* message =
	        (NvAudioFxMessage*)m_FxNotifier->RcvMessageBuffer;

	while (retry < 5) {
		e = NvRmTransportConnect(m_FxNotifier->hTransport, 5000);
		if (e == NvSuccess)
			break;

		retry++;
	}
	if (e != NvSuccess) {
			snd_printk(KERN_ERR "NvRmTransportConnect failed!\n");
		m_FxNotifier->Connected = 0;
		goto EXIT;
	}

	m_FxNotifier->Connected = 1;
	while (1) {
		NvOsSemaphoreWait(m_FxNotifier->hTransportSemaphore);
		if (m_FxNotifier->Exit) {
			break;
		}

		e = NvRmTransportRecvMsg(m_FxNotifier->hTransport,
		                         message,
		                         256,
		                         &messageSize);
		if (e == NvSuccess) {
			switch (message->Event) {
			case NvAudioFxEventBufferDone:{
				NvAudioFxBufferDoneMessage* bdm =
				      (NvAudioFxBufferDoneMessage*)message;
				struct pcm_runtime_data* prtd =
				      (struct pcm_runtime_data*)bdm->m.pContext;

				 up(&prtd->buf_done_sem);
			}
			break;

			case NvAudioFxEventEndOfStream:
			break;

			case NvAudioFxEventStateChange:{
				NvAudioFxStateChangeMessage* scm =
				      (NvAudioFxStateChangeMessage*)message;
				struct pcm_runtime_data* prtd =
				      (struct pcm_runtime_data*)scm->m.pContext;
				up(&prtd->stop_done_sem);
			}
			break;

			case NvAudioFxEventControlChange:{
				NvAudioFxControlChangeMessage* ccm =
					(NvAudioFxControlChangeMessage*)message;

				if (message->hFx ==
					(NvAudioFxHandle)audio_context->mi2s1) {
					if (ccm->Property == NvAudioFxIoProperty_OutputAvailable) {
						NvAudioFxIoDeviceControlChangeMessage* iccm =
							(NvAudioFxIoDeviceControlChangeMessage*)message;

						audio_context->mi2s1_device_available = iccm->IoDevice;
						tegra_audiofx_route(audio_context);
					}

				}
				else if (message->hFx ==
					(NvAudioFxHandle)audio_context->mroute) {
					if (ccm->Property == NvAudioFxIoProperty_OutputAvailable) {
						NvAudioFxIoDeviceControlChangeMessage* iccm =
							(NvAudioFxIoDeviceControlChangeMessage*)message;

						audio_context->mspdif_device_available = iccm->IoDevice;
						tegra_audiofx_route(audio_context);
					}
				}
			}
			break;

			default:
				pr_debug("Unhandled event 0x%08x\n", message->Event);
				break;
			}
		}
	}

EXIT:
	return;
}
Beispiel #8
0
static void AlsaTransportServiceThread(void *arg)
{
	NvError status = NvSuccess;
	static NvFxTransportMessageResultBuffer in;
	NvU32 messageSize = 0;
	int retry = 0;
#define transport_complete(comp)                                               \
	complete((struct completion*)comp);

	while (retry < 5 ) {
		status = NvRmTransportConnect(atrans->hRmTransport,
					TEGRA_TRANSPORT_CONNECT_TIMEOUT);
		if (status == NvSuccess)
			break;
		retry++;
	}

	if (status) {
		snd_printk(KERN_ERR "AlsaTransportServiceThread: Failed to \
			connect to remote end. Giving up ! \n");
		atrans->TransportConnected = 0;
		return;
	}

	atrans->TransportConnected = 1;

	while (!atrans->ShutDown) {
		NvOsSemaphoreWait(atrans->hServiceSema);
		if (atrans->ShutDown)
			break;

		status = NvRmTransportRecvMsg(atrans->hRmTransport,
					&in,
					sizeof(NvFxTransportMessageResultBuffer),
					&messageSize);
		if (status == NvSuccess) {
			switch (in.Message.Message) {
			case NVFXTRANSPORT_MESSAGE_MIXER_OPEN: {
				*in.MixerOpen.phMixer = in.MixerOpen.hMixer;
// 20110223, , media server restart 2 [start]
				*in.MixerOpen.pReturnError = in.MixerOpen.ReturnError;
// 20110223, , media server restart 2 [end]				
				transport_complete(in.MixerOpen.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_MIXER_CLOSE: {
				transport_complete(in.MixerClose.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_CREATE_OBJECT: {
				*in.CreateObject.phObject =
				        in.CreateObject.hObject;
				transport_complete(in.CreateObject.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_DESTROY_OBJECT: {
				transport_complete(in.DestroyObject.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_MAP_BUFFER: {
				*in.MapBuffer.phMixBuffer =
				        in.MapBuffer.hMixBuffer;
				transport_complete(in.MapBuffer.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_UNMAP_BUFFER: {
				transport_complete(in.UnmapBuffer.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_GET_PROPERTY: {
				*in.GetProperty.pReturnError =
				        in.GetProperty.ReturnError;
				if (in.GetProperty.ReturnError == NvSuccess) {
					NvOsMemcpy(in.GetProperty.pProperty,
					           in.GetProperty.PropertyData,
					           in.GetProperty.Size);
				}
				transport_complete(in.GetProperty.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_SET_PROPERTY: {
				*in.SetProperty.pReturnError =
				        in.SetProperty.ReturnError;
				transport_complete(in.SetProperty.pPrivateData);
			}
			break;

			case NVFXTRANSPORT_MESSAGE_STREAM_ADD_BUFFER: {
				*in.StreamAddBuffer.pReturnError =
				        in.StreamAddBuffer.ReturnError;
				transport_complete(in.StreamAddBuffer.pPrivateData);
			}
			break;

			default:
				break;
			}
		}
	}

}
Beispiel #9
0
void NvOdmOsSemaphoreWait(NvOdmOsSemaphoreHandle semaphore)
{
    NvOsSemaphoreWait((NvOsSemaphoreHandle)semaphore);
}