1bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "fw_pvt.h"
2bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_parser_ipclib_config.h"
3bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_common_defs.h"
4bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_parser.h"
5bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#include "viddec_fw_debug.h"
6bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
7bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/* This define makes sure that the structure is stored in Local memory.
8bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee   This is shared memory between host and FW.*/
9bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevolatile dmem_t _dmem __attribute__ ((section (".exchange")));
10bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/* Debug index should be disbaled for Production FW */
11bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeuint32_t dump_ptr=0;
12bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeuint32_t timer=0;
13bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
14bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/* Auto Api definitions */
15bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeismd_api_group viddec_fw_api_array[2];
16bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
17bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeextern void viddec_fw_parser_register_callbacks(void);
18bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
19bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
20bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  initialize firmware SVEN TX Output
21bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
22bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
23bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeint SMDEXPORT viddec_fw_parser_sven_init(struct SVEN_FW_Globals  *sven_fw_globals )
24bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
25bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    extern int sven_fw_set_globals(struct SVEN_FW_Globals  *fw_globals );
26bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return(sven_fw_set_globals(sven_fw_globals));
27bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
28bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
29bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
30bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_check_watermark_boundary
31bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function figures out if we crossesd watermark boundary on input data.
32bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * before represents the ES Queue data when we started and current represents ES Queue data
33bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * when we are ready to swap.Threshold is the amount of data specified by the driver to trigger an
34bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * interrupt.
35bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * We return true if threshold is between before and current.
36bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
37bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
38bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline uint32_t viddec_fw_check_watermark_boundary(uint32_t before, uint32_t current, uint32_t threshold)
39bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
40bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return ((before >= threshold) && (current < threshold));
41bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
42bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
43bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
44bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_get_total_input_Q_data
45bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function figures out how much data is available in input queue of the FW
46bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
47bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
48bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic uint32_t viddec_fw_get_total_input_Q_data(uint32_t indx)
49bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
50bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem);
51bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t ret;
52bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t pos=0;
53bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FW_IPC_ReceiveQue   *rcv_q;
54bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
55bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    rcv_q = &fwipc->rcv_q[indx];
56bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* count the cubby buffer which we already read if present */
57bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    ret = (_dmem.stream_info[indx].buffered_data) ? CONFIG_IPC_MESSAGE_MAX_SIZE:0;
58bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    ret += ipc_mq_read_avail(&rcv_q->mq, (int32_t *)&pos);
59bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return ret;
60bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
61bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
62bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
63bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  mfd_round_robin
64bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Params:
65bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *        [in]  pri: Priority of the stream
66bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *        [in] indx: stream id number of the last stream that was scheduled.
67bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *        [out] qnum: Stream id of priority(pri) which has data.
68bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for figuring out which stream needs to be scheduled next.
69bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * It starts after the last scheduled stream and walks through all streams until it finds
70bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * a stream which is of required priority, in start state, has space on output and data in
71bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * input.
72bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If no such stream is found qnum is not updated and return value is 0.
73bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If a stream is found then qnum is updated with that id and function returns 1.
74bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
75bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
76bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
77bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeuint32_t mfd_round_robin(uint32_t pri, int32_t *qnum, int32_t indx)
78bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
79bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem);
80bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t i = CONFIG_IPC_FW_MAX_RX_QUEUES;
81bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t ret = 0;
82bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* Go through all queues until we find a valid queue of reqd priority */
83bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    while(i>0)
84bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
85bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        indx++;
86bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if(indx >=  CONFIG_IPC_FW_MAX_RX_QUEUES) indx = 0;
87bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
88bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        /* We should look only at queues which match priority and
89bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee           in running state */
90bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if( (_dmem.stream_info[indx].state == 1)
91bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            && (_dmem.stream_info[indx].priority == pri))
92bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
93bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            uint32_t inpt_avail=0, output_avail=0, wklds_avail =0 , pos;
94bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            FW_IPC_ReceiveQue   *rcv_q;
95bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            rcv_q = &fwipc->rcv_q[indx];
96bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            inpt_avail = (_dmem.stream_info[indx].buffered_data > 0) || (ipc_mq_read_avail(&rcv_q->mq, (int32_t *)&pos) > 0);
97bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* we have to check for two workloads to protect against error cases where we might have to push both current and next workloads */
98bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            output_avail = FwIPC_SpaceAvailForMessage(fwipc, &fwipc->snd_q[indx], CONFIG_IPC_MESSAGE_MAX_SIZE, &pos) >= 2;
99bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            pos = 0;
100bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* Need at least current and next to proceed */
101bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            wklds_avail =  (ipc_mq_read_avail(&fwipc->wkld_q[indx].mq, (int32_t *)&pos) >= (CONFIG_IPC_MESSAGE_MAX_SIZE << 1));
102bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            if(inpt_avail && output_avail && wklds_avail)
103bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {/* Success condition: we have some data on input and enough space on output queue */
104bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                *qnum = indx;
105bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                ret =1;
106bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                break;
107bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
108bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
109bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        i--;
110bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
111bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return ret;
112bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
113bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void mfd_setup_emitter(FW_IPC_Handle *fwipc, FW_IPC_ReceiveQue *rcv_q, mfd_pk_strm_cxt *cxt)
114bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
115bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t ret1=0,ret=0;
116bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* We don't check return values for the peek as round robin guarantee's that we have required free workloads */
117bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    ret = FwIPC_PeekReadMessage(fwipc, rcv_q, (char *)&(cxt->wkld1), sizeof(ipc_msg_data), 0);
118bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    ret1 = FwIPC_PeekReadMessage(fwipc, rcv_q, (char *)&(cxt->wkld2), sizeof(ipc_msg_data), 1);
119bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_emit_update(&(cxt->pm.emitter), cxt->wkld1.phys, cxt->wkld2.phys, cxt->wkld1.len, cxt->wkld2.len);
120bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
121bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
122bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void mfd_init_swap_memory(viddec_pm_cxt_t *pm, uint32_t codec_type, uint32_t start_addr, uint32_t clean)
123bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
124bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t *persist_mem;
125bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    persist_mem = (uint32_t *)(start_addr | GV_DDR_MEM_MASK);
126bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_pm_init_context(pm,codec_type, persist_mem, clean);
127bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    pm->sc_prefix_info.first_sc_detect = 1;
128bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_emit_init(&(pm->emitter));
129bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
130bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
131bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevoid output_omar_wires( unsigned int value )
132bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
133bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#ifdef RTL_SIMULATION
134bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    reg_write(CONFIG_IPC_ROFF_HOST_DOORBELL, value );
135bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#endif
136bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
137bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
138bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
139bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_init_swap_memory
140bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for seeting the swap memory to a good state for current stream.
141bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * The swap parameter tells us whether we need to dma the context to local memory.
142bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * We call init on emitter and parser manager which inturn calls init of the codec we are opening the stream for.
143bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
144bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
145bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
146bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevoid viddec_fw_init_swap_memory(unsigned int stream_id, unsigned int swap, unsigned int clean)
147bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
148bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    mfd_pk_strm_cxt *cxt;
149bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    mfd_stream_info *cxt_swap;
150bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    cxt = (mfd_pk_strm_cxt *)&(_dmem.srm_cxt);
151bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    cxt_swap = (mfd_stream_info *)&(_dmem.stream_info[stream_id]);
152bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
153bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if(swap)
154bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {/* Swap context into local memory */
155bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), false, false);
156bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
157bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
158bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
159bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        mfd_init_swap_memory(&(cxt->pm), cxt_swap->strm_type, cxt_swap->ddr_cxt+cxt_swap->cxt_size, clean);
160bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        cxt_swap->wl_time = 0;
161bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        cxt_swap->es_time = 0;
162bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
163bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if(swap)
164bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {/* Swap context into DDR */
165bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), true, false);
166bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
167bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
168bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
169bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
170bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_push_current_frame_to_output
171bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is a helper function to read a workload from input queue and push to output queue.
172bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is called when are done with a frame.
173bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
174bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
175bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_push_current_frame_to_output(FW_IPC_Handle *fwipc, uint32_t cur)
176bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
177bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    ipc_msg_data wkld_to_push;
178bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FwIPC_ReadMessage(fwipc, &fwipc->wkld_q[cur], (char *)&(wkld_to_push), sizeof(ipc_msg_data));
179bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FwIPC_SendMessage(fwipc, cur, (char *)&(wkld_to_push),  sizeof(ipc_msg_data));
180bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
181bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
182bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
183bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_get_next_stream_to_schedule
184bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is a helper function to figure out which active stream needs to be scheduled next.
185bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If none of the streams are active it returns -1.
186bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
187bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
188bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int viddec_fw_get_next_stream_to_schedule(void)
189bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
190bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t cur = -1;
191bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
192bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if(mfd_round_robin(viddec_stream_priority_REALTIME, &cur, _dmem.g_pk_data.high_id))
193bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
194bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        /* On success store the stream id */
195bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        _dmem.g_pk_data.high_id = cur;
196bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
197bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    else
198bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
199bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        /* Check Low priority Queues, Since we couldn't find a valid realtime stream */
200bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if(mfd_round_robin(viddec_stream_priority_BACKGROUND, &cur, _dmem.g_pk_data.low_id))
201bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
202bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            _dmem.g_pk_data.low_id = cur;
203bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
204bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
205bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
206bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return cur;
207bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
208bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
209bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
210bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function: viddec_fw_update_pending_interrupt_flag
211bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This is a helper function to figure out if we need to mark an interrupt pending for this stream.
212bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * We update status value here if we find any of the interrupt conditions are true.
213bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If this stream has a interrupt pending which we could not send to host, we don't overwrite past status info.
214bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
215bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
216bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_update_pending_interrupt_flag(int32_t cur, mfd_stream_info *cxt_swap, uint8_t pushed_a_workload,
217bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                                           uint32_t es_Q_data_at_start)
218bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
219bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if(_dmem.int_status[cur].mask)
220bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
221bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if(!cxt_swap->pending_interrupt)
222bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
223bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            uint32_t es_Q_data_now;
224bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            uint8_t wmark_boundary_reached=false;
225bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            es_Q_data_now = viddec_fw_get_total_input_Q_data((uint32_t)cur);
226bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            wmark_boundary_reached = viddec_fw_check_watermark_boundary(es_Q_data_at_start, es_Q_data_now, cxt_swap->low_watermark);
227bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            _dmem.int_status[cur].status = 0;
228bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            if(pushed_a_workload)
229bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {
230bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                _dmem.int_status[cur].status |= VIDDEC_FW_WKLD_DATA_AVAIL;
231bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
232bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            if(wmark_boundary_reached)
233bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {
234bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                _dmem.int_status[cur].status |= VIDDEC_FW_INPUT_WATERMARK_REACHED;
235bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
236bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            cxt_swap->pending_interrupt = ( _dmem.int_status[cur].status != 0);
237bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
238bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
239bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    else
240bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
241bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        cxt_swap->pending_interrupt = false;
242bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
243bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
244bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
245bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_handle_error_and_inband_messages(int32_t cur, uint32_t pm_ret)
246bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
247bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem);
248bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
249bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_fw_push_current_frame_to_output(fwipc, cur);
250bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    switch(pm_ret)
251bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
252bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        case PM_EOS:
253bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        case PM_OVERFLOW:
254bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
255bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            viddec_fw_init_swap_memory(cur, false, true);
256bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
257bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        break;
258bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        case PM_DISCONTINUITY:
259bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
260bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            viddec_fw_init_swap_memory(cur, false, false);
261bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
262bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        break;
263bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        default:
264bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            break;
265bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
266bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
267bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
268bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevoid viddec_fw_debug_scheduled_stream_state(int32_t indx, int32_t start)
269bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
270bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem);
271bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t inpt_avail=0, output_avail=0, wklds_avail =0 , pos;
272bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FW_IPC_ReceiveQue   *rcv_q;
273bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t message;
274bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
275bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    message = (start) ? SVEN_MODULE_EVENT_GV_FW_PK_SCHDL_STRM_START: SVEN_MODULE_EVENT_GV_FW_PK_SCHDL_STRM_END;
276bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    rcv_q = &fwipc->rcv_q[indx];
277bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    inpt_avail = ipc_mq_read_avail(&rcv_q->mq, (int32_t *)&pos);
278bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    inpt_avail += ((_dmem.stream_info[indx].buffered_data > 0) ? CONFIG_IPC_MESSAGE_MAX_SIZE: 0);
279bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    inpt_avail = inpt_avail >> 4;
280bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    pos = 0;
281bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    output_avail = ipc_mq_read_avail(&fwipc->snd_q[indx].mq, (int32_t *)&pos);
282bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    output_avail = output_avail >> 4;
283bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    pos = 0;
284bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    wklds_avail =  ipc_mq_read_avail(&fwipc->wkld_q[indx].mq, (int32_t *)&pos);
285bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    wklds_avail = wklds_avail >> 4;
286bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    WRITE_SVEN(message, (int)indx, (int)inpt_avail, (int)output_avail,
287bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee               (int)wklds_avail, 0, 0);
288bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
289bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
290bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
291bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_process_async_queues(A.K.A -> Parser Kernel)
292bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for handling the asynchronous queues.
293bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *
294bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * The first step is to figure out which stream to run. The current algorithm
295bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * will go through all high priority queues for a valid stream, if not found we
296bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * go through lower priority queues.
297bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *
298bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * If a valid stream is found we swap the required context from DDR to DMEM and do all necessary
299bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * things to setup the stream.
300bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Once a stream is setup we call the parser manager and wait until a wrkld is created or no more input
301bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * data left.
302bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Once we find a wkld we push it to host and save the current context to DDR.
303bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
304bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
305bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
306bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int32_t viddec_fw_process_async_queues()
307bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
308bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t cur = -1;
309bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
310bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    cur = viddec_fw_get_next_stream_to_schedule();
311bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
312bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if(cur != -1)
313bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
314bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        FW_IPC_Handle *fwipc = GET_IPC_HANDLE(_dmem);
315bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        FW_IPC_ReceiveQue   *rcv_q;
316bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        /* bits captured by OMAR */
317bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        output_omar_wires( 0x0 );
318bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        rcv_q = &fwipc->rcv_q[cur];
319bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
320bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            mfd_pk_strm_cxt *cxt;
321bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            mfd_stream_info *cxt_swap;
322bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            cxt = (mfd_pk_strm_cxt *)&(_dmem.srm_cxt);
323bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            cxt_swap = (mfd_stream_info *)&(_dmem.stream_info[cur]);
324bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
325bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* Step 1: Swap rodata to local memory. Not doing this currently as all the rodata fits in local memory. */
326bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {/* Step 2: Swap context into local memory */
327bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), false, false);
328bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
329bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* Step 3:setup emitter by reading input data and workloads and initialising it */
330bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            mfd_setup_emitter(fwipc, &fwipc->wkld_q[cur], cxt);
331bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            viddec_fw_debug_scheduled_stream_state(cur, true);
332bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* Step 4: Call Parser Manager until workload done or No more ES buffers */
333bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {
334bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                ipc_msg_data *data = 0;
335bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                uint8_t stream_active = true, pushed_a_workload=false;
336bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                uint32_t pm_ret = PM_SUCCESS, es_Q_data_at_start;
337bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                uint32_t start_time, time=0;
338bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
339bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                start_time = set_wdog(VIDDEC_WATCHDOG_COUNTER_MAX);
340bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                timer=0;
341bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                es_Q_data_at_start = viddec_fw_get_total_input_Q_data((uint32_t)cur);
342bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                do
343bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                {
344bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    output_omar_wires( 0x1 );
345bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    {
346bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        uint32_t es_t0,es_t1;
347bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        get_wdog(&es_t0);
348bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        pm_ret = viddec_pm_parse_es_buffer(&(cxt->pm), cxt_swap->strm_type, data);
349bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        get_wdog(&es_t1);
350bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        cxt_swap->es_time += get_total_ticks(es_t0, es_t1);
351bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    }
352bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    switch(pm_ret)
353bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    {
354bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        case PM_EOS:
355bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        case PM_WKLD_DONE:
356bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        case PM_OVERFLOW:
357bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        case PM_DISCONTINUITY:
358bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        {/* Finished a frame worth of data or encountered fatal error*/
359bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            stream_active = false;
360bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        }
361bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        break;
362bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        case PM_NO_DATA:
363bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        {
364bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            uint32_t next_ret=0;
365bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            if ( (NULL != data) && (0 != cxt_swap->es_time) )
366bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            {
367bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                /* print performance info for this buffer */
368bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                WRITE_SVEN(SVEN_MODULE_EVENT_GV_FW_PK_ES_DONE, (int)cur, (int)cxt_swap->es_time, (int)cxt->input.phys,
369bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                           (int)cxt->input.len, (int)cxt->input.id, (int)cxt->input.flags );
370bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                cxt_swap->es_time = 0;
371bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            }
372bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
373bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            next_ret = FwIPC_ReadMessage(fwipc, rcv_q, (char *)&(cxt->input), sizeof(ipc_msg_data));
374bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            if(next_ret != 0)
375bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            {
376bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                data = &(cxt->input);
377bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                WRITE_SVEN(SVEN_MODULE_EVENT_GV_FW_PK_ES_START, (int)cur, (int)cxt_swap->wl_time,
378bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                           (int)cxt->input.phys, (int)cxt->input.len, (int)cxt->input.id, (int)cxt->input.flags );
379bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            }
380bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            else
381bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            {/* No data on input queue */
382bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                cxt_swap->buffered_data = 0;
383bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                stream_active = false;
384bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            }
385bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        }
386bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        break;
387bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        default:
388bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        {/* Not done with current buffer */
389bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            data = NULL;
390bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        }
391bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        break;
392bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    }
393bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                }while(stream_active);
394bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                get_wdog(&time);
395bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                cxt_swap->wl_time += get_total_ticks(start_time, time);
396bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                /* Step 5: If workload done push workload out */
397bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                switch(pm_ret)
398bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                {
399bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    case PM_EOS:
400bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    case PM_WKLD_DONE:
401bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    case PM_OVERFLOW:
402bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    case PM_DISCONTINUITY:
403bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    {/* Push current workload as we are done with the frame */
404bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        cxt_swap->buffered_data = (PM_WKLD_DONE == pm_ret) ? true: false;
405bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        viddec_pm_update_time(&(cxt->pm), cxt_swap->wl_time);
406bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
407bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        /* xmit performance info for this workload output */
408bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        WRITE_SVEN( SVEN_MODULE_EVENT_GV_FW_PK_WL_DONE, (int)cur, (int)cxt_swap->wl_time, (int)cxt->wkld1.phys,
409bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                                    (int)cxt->wkld1.len, (int)cxt->wkld1.id, (int)cxt->wkld1.flags );
410bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        cxt_swap->wl_time = 0;
411bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
412bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        viddec_fw_push_current_frame_to_output(fwipc, cur);
413bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        if(pm_ret != PM_WKLD_DONE)
414bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        {
415bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                            viddec_fw_handle_error_and_inband_messages(cur, pm_ret);
416bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        }
417bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        pushed_a_workload = true;
418bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    }
419bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    break;
420bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                    default:
421bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                        break;
422bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                }
423bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                /* Update information on whether we have active interrupt for this stream */
424bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                viddec_fw_update_pending_interrupt_flag(cur, cxt_swap, pushed_a_workload, es_Q_data_at_start);
425bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
426bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            viddec_fw_debug_scheduled_stream_state(cur, false);
427bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* Step 6: swap context into DDR */
428bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {
429bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                cp_using_dma(cxt_swap->ddr_cxt, (uint32_t) &(cxt->pm), sizeof(viddec_pm_cxt_t), true, false);
430bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
431bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
432bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
433bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
434bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return cur;
435bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
436bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
437bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
438bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
439bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  process_command
440bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This magic function figures out which function to excute based on autoapi.
441bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
442bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
443bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
444bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void process_command(uint32_t cmd_id, unsigned char *command)
445bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
446bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t groupid = ((cmd_id >> 24) - 13) & 0xff;
447bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t funcid = cmd_id & 0xffffff;
448bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* writing func pointer to hsot doorbell */
449bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    output_omar_wires( (int) viddec_fw_api_array[groupid].unmarshal[funcid] );
450bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    WRITE_SVEN( SVEN_MODULE_EVENT_GV_FW_AUTOAPI_CMD,(int) cmd_id, (int) command, ((int *)command)[0],
451bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                ((int *)command)[1], ((int *)command)[2], ((int *)command)[3] );
452bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
453bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_fw_api_array[groupid].unmarshal[funcid](0, command);
454bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
455bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
456bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
457bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
458bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_process_sync_queues(A.K.A auto api)
459bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Params:
460bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *       [in] msg: common sync structure where all required parameters are present for autoapi.
461bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *
462bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is responsible for handling synchronous messages. All synchronous messages
463bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * are handled through auto api.
464bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * what are synchronous messages?  Anything releated to teardown or opening a stream Ex: open, close, flush etc.
465bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *
466bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Only once synchronous message at a time. When a synchronous message its id is usually in cp doorbell. Once
467bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * we are done handling synchronous message through auto api we release doorbell to let the host write next
468bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * message.
469bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
470bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
471bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
472bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int32_t viddec_fw_process_sync_queues(unsigned char *msg)
473bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
474bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    int32_t ret = -1;
475bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
476bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if(0 == reg_read(CONFIG_IPC_ROFF_RISC_DOORBELL_STATUS))
477bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
478bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        uint32_t command1=0;
479bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        command1 = reg_read(CONFIG_IPC_ROFF_RISC_RX_DOORBELL);
480bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        process_command(command1, msg);
481bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        reg_write(CONFIG_IPC_ROFF_RISC_DOORBELL_STATUS, 0x2); /* Inform Host we are done with this message */
482bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        ret = 0;
483bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
484bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return ret;
485bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
486bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
487bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
488bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_check_for_pending_int
489bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function walks through all active streams to see if atleast one stream has a pending interrupt
490bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * and returns true if it finds one.
491bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
492bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
493bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline uint32_t viddec_fw_check_for_pending_int(void)
494bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
495bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t i=0, ret=false;
496bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* start from 0 to max streams that fw can handle*/
497bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    while(i < FW_SUPPORTED_STREAMS)
498bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
499bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if(_dmem.stream_info[i].state == 1)
500bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
501bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            if((_dmem.stream_info[i].pending_interrupt) && _dmem.int_status[i].mask)
502bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {
503bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                ret = true;
504bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
505bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            else
506bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            {/* If this is not in INT state clear the status before sending it to host */
507bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee                _dmem.int_status[i].status = 0;
508bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            }
509bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
510bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        i++;
511bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
512bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return ret;
513bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
514bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
515bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
516bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_clear_processed_int
517bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function walks through all active streams to clear pending interrupt state.This is
518bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * called after a INT was issued.
519bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
520bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
521bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline void viddec_fw_clear_processed_int(void)
522bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
523bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    uint32_t i=0;
524bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* start from 0 to max streams that fw can handle*/
525bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    while(i < FW_SUPPORTED_STREAMS)
526bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
527bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        //if(_dmem.stream_info[i].state == 1)
528bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        _dmem.stream_info[i].pending_interrupt = false;
529bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        i++;
530bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
531bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return;
532bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
533bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
534bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
535bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  viddec_fw_int_host
536bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function interrupts host if data is available for host or any other status
537bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * is valid which the host configures the FW to.
538bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * There is only one interrupt line so this is a shared Int for all streams, Host should
539bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * look at status of all streams when it receives a Int.
540bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * The FW will interrupt the host only if host doorbell is free, in other words the host
541bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * should always make the doorbell free at the End of its ISR.
542bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
543bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
544bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
545bd8388b4555645b3d29abc6a94c303638064d69awonjong.leestatic inline int32_t viddec_fw_int_host()
546bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
547bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* We Interrupt the host only if host is ready to receive an interrupt */
548bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    if((reg_read(CONFIG_IPC_ROFF_HOST_DOORBELL_STATUS) & GV_DOORBELL_STATS) == GV_DOORBELL_STATS)
549bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
550bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if(viddec_fw_check_for_pending_int())
551bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
552bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* If a pending interrupt is found trigger INT */
553bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            reg_write(CONFIG_IPC_ROFF_HOST_DOORBELL, VIDDEC_FW_PARSER_IPC_HOST_INT);
554bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            /* Clear all stream's pending Interrupt info since we use a global INT for all streams */
555bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            viddec_fw_clear_processed_int();
556bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
557bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
558bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return 1;
559bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
560bd8388b4555645b3d29abc6a94c303638064d69awonjong.leevolatile unsigned int stack_corrupted __attribute__ ((section (".stckovrflwchk")));
561bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee/*------------------------------------------------------------------------------
562bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * Function:  main
563bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * This function is the main firmware function. Its a infinite loop where it polls
564bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * for messages and processes them if they are available. Currently we ping pong between
565bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * synchronous and asynchronous messages one at a time. If we have multiple aysnchronous
566bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * queues we always process only one between synchronous messages.
567bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *
568bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * For multiple asynchronous queues we round robin through the high priorities first and pick
569bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * the first one available. Next time when we come around for asynchronous message we start
570bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * from the next stream onwards so this guarantees that we give equal time slices for same
571bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * priority queues. If no high priority queues are active we go to low priority queues and repeat
572bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee * the same process.
573bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee *------------------------------------------------------------------------------
574bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee */
575bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
576bd8388b4555645b3d29abc6a94c303638064d69awonjong.leeint main(void)
577bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee{
578bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    unsigned char *msg = (uint8_t *)&(_dmem.buf.data[0]);
579bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
580bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* We wait until host reads sync message */
581bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    reg_write(CONFIG_IPC_ROFF_HOST_RX_DOORBELL, GV_FW_IPC_HOST_SYNC);
582bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee
583bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    while ( GV_DOORBELL_STATS != reg_read(CONFIG_IPC_ROFF_HOST_DOORBELL_STATUS) )
584bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    { /*poll register until done bit is set */
585bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee      /* Host re-writes Vsparc DRAM (BSS) in this loop and will hit the DONE bit when complete */
586bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
587bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    enable_intr();
588bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    /* Initialize State for queues */
589bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_fw_parser_register_callbacks();
590bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    FwIPC_Initialize(GET_IPC_HANDLE(_dmem), (volatile char *)msg);
591bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    _dmem.g_pk_data.high_id = _dmem.g_pk_data.low_id = -1;
592bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    viddec_pm_init_ops();
593bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    stack_corrupted = 0xDEADBEEF;
594bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    while(1)
595bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    {
596bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        viddec_fw_process_sync_queues(msg);
597bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        viddec_fw_process_async_queues();
598bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        viddec_fw_int_host();
599bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#if 0
600bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        if(stack_corrupted != 0xDEADBEEF)
601bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        {
602bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            WRITE_SVEN(SVEN_MODULE_EVENT_GV_FW_FATAL_STACK_CORRPON, 0, 0, 0, 0, 0, 0);
603bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee            while(1);
604bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee        }
605bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee#endif
606bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    }
607bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee    return 1;
608bd8388b4555645b3d29abc6a94c303638064d69awonjong.lee}
609