GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / media / platform / qcom / venus / hfi_venus.c
1 /*
2  * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
3  * Copyright (C) 2017 Linaro Ltd.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 and
7  * only version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15
16 #include <linux/delay.h>
17 #include <linux/device.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/interrupt.h>
20 #include <linux/iopoll.h>
21 #include <linux/kernel.h>
22 #include <linux/qcom_scm.h>
23 #include <linux/slab.h>
24
25 #include "core.h"
26 #include "hfi_cmds.h"
27 #include "hfi_msgs.h"
28 #include "hfi_venus.h"
29 #include "hfi_venus_io.h"
30
31 #define HFI_MASK_QHDR_TX_TYPE           0xff000000
32 #define HFI_MASK_QHDR_RX_TYPE           0x00ff0000
33 #define HFI_MASK_QHDR_PRI_TYPE          0x0000ff00
34 #define HFI_MASK_QHDR_ID_TYPE           0x000000ff
35
36 #define HFI_HOST_TO_CTRL_CMD_Q          0
37 #define HFI_CTRL_TO_HOST_MSG_Q          1
38 #define HFI_CTRL_TO_HOST_DBG_Q          2
39 #define HFI_MASK_QHDR_STATUS            0x000000ff
40
41 #define IFACEQ_NUM                      3
42 #define IFACEQ_CMD_IDX                  0
43 #define IFACEQ_MSG_IDX                  1
44 #define IFACEQ_DBG_IDX                  2
45 #define IFACEQ_MAX_BUF_COUNT            50
46 #define IFACEQ_MAX_PARALLEL_CLNTS       16
47 #define IFACEQ_DFLT_QHDR                0x01010000
48
49 #define POLL_INTERVAL_US                50
50
51 #define IFACEQ_MAX_PKT_SIZE             1024
52 #define IFACEQ_MED_PKT_SIZE             768
53 #define IFACEQ_MIN_PKT_SIZE             8
54 #define IFACEQ_VAR_SMALL_PKT_SIZE       100
55 #define IFACEQ_VAR_LARGE_PKT_SIZE       512
56 #define IFACEQ_VAR_HUGE_PKT_SIZE        (1024 * 12)
57
58 enum tzbsp_video_state {
59         TZBSP_VIDEO_STATE_SUSPEND = 0,
60         TZBSP_VIDEO_STATE_RESUME
61 };
62
63 struct hfi_queue_table_header {
64         u32 version;
65         u32 size;
66         u32 qhdr0_offset;
67         u32 qhdr_size;
68         u32 num_q;
69         u32 num_active_q;
70 };
71
72 struct hfi_queue_header {
73         u32 status;
74         u32 start_addr;
75         u32 type;
76         u32 q_size;
77         u32 pkt_size;
78         u32 pkt_drop_cnt;
79         u32 rx_wm;
80         u32 tx_wm;
81         u32 rx_req;
82         u32 tx_req;
83         u32 rx_irq_status;
84         u32 tx_irq_status;
85         u32 read_idx;
86         u32 write_idx;
87 };
88
89 #define IFACEQ_TABLE_SIZE       \
90         (sizeof(struct hfi_queue_table_header) +        \
91          sizeof(struct hfi_queue_header) * IFACEQ_NUM)
92
93 #define IFACEQ_QUEUE_SIZE       (IFACEQ_MAX_PKT_SIZE *  \
94         IFACEQ_MAX_BUF_COUNT * IFACEQ_MAX_PARALLEL_CLNTS)
95
96 #define IFACEQ_GET_QHDR_START_ADDR(ptr, i)      \
97         (void *)(((ptr) + sizeof(struct hfi_queue_table_header)) +      \
98                 ((i) * sizeof(struct hfi_queue_header)))
99
100 #define QDSS_SIZE               SZ_4K
101 #define SFR_SIZE                SZ_4K
102 #define QUEUE_SIZE              \
103         (IFACEQ_TABLE_SIZE + (IFACEQ_QUEUE_SIZE * IFACEQ_NUM))
104
105 #define ALIGNED_QDSS_SIZE       ALIGN(QDSS_SIZE, SZ_4K)
106 #define ALIGNED_SFR_SIZE        ALIGN(SFR_SIZE, SZ_4K)
107 #define ALIGNED_QUEUE_SIZE      ALIGN(QUEUE_SIZE, SZ_4K)
108 #define SHARED_QSIZE            ALIGN(ALIGNED_SFR_SIZE + ALIGNED_QUEUE_SIZE + \
109                                       ALIGNED_QDSS_SIZE, SZ_1M)
110
111 struct mem_desc {
112         dma_addr_t da;  /* device address */
113         void *kva;      /* kernel virtual address */
114         u32 size;
115         unsigned long attrs;
116 };
117
118 struct iface_queue {
119         struct hfi_queue_header *qhdr;
120         struct mem_desc qmem;
121 };
122
123 enum venus_state {
124         VENUS_STATE_DEINIT = 1,
125         VENUS_STATE_INIT,
126 };
127
128 struct venus_hfi_device {
129         struct venus_core *core;
130         u32 irq_status;
131         u32 last_packet_type;
132         bool power_enabled;
133         bool suspended;
134         enum venus_state state;
135         /* serialize read / write to the shared memory */
136         struct mutex lock;
137         struct completion pwr_collapse_prep;
138         struct completion release_resource;
139         struct mem_desc ifaceq_table;
140         struct mem_desc sfr;
141         struct iface_queue queues[IFACEQ_NUM];
142         u8 pkt_buf[IFACEQ_VAR_HUGE_PKT_SIZE];
143         u8 dbg_buf[IFACEQ_VAR_HUGE_PKT_SIZE];
144 };
145
146 static bool venus_pkt_debug;
147 static int venus_fw_debug = HFI_DEBUG_MSG_ERROR | HFI_DEBUG_MSG_FATAL;
148 static bool venus_sys_idle_indicator;
149 static bool venus_fw_low_power_mode = true;
150 static int venus_hw_rsp_timeout = 1000;
151 static bool venus_fw_coverage;
152
153 static void venus_set_state(struct venus_hfi_device *hdev,
154                             enum venus_state state)
155 {
156         mutex_lock(&hdev->lock);
157         hdev->state = state;
158         mutex_unlock(&hdev->lock);
159 }
160
161 static bool venus_is_valid_state(struct venus_hfi_device *hdev)
162 {
163         return hdev->state != VENUS_STATE_DEINIT;
164 }
165
166 static void venus_dump_packet(struct venus_hfi_device *hdev, const void *packet)
167 {
168         size_t pkt_size = *(u32 *)packet;
169
170         if (!venus_pkt_debug)
171                 return;
172
173         print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1, packet,
174                        pkt_size, true);
175 }
176
177 static int venus_write_queue(struct venus_hfi_device *hdev,
178                              struct iface_queue *queue,
179                              void *packet, u32 *rx_req)
180 {
181         struct hfi_queue_header *qhdr;
182         u32 dwords, new_wr_idx;
183         u32 empty_space, rd_idx, wr_idx, qsize;
184         u32 *wr_ptr;
185
186         if (!queue->qmem.kva)
187                 return -EINVAL;
188
189         qhdr = queue->qhdr;
190         if (!qhdr)
191                 return -EINVAL;
192
193         venus_dump_packet(hdev, packet);
194
195         dwords = (*(u32 *)packet) >> 2;
196         if (!dwords)
197                 return -EINVAL;
198
199         rd_idx = qhdr->read_idx;
200         wr_idx = qhdr->write_idx;
201         qsize = qhdr->q_size;
202         /* ensure rd/wr indices's are read from memory */
203         rmb();
204
205         if (wr_idx >= rd_idx)
206                 empty_space = qsize - (wr_idx - rd_idx);
207         else
208                 empty_space = rd_idx - wr_idx;
209
210         if (empty_space <= dwords) {
211                 qhdr->tx_req = 1;
212                 /* ensure tx_req is updated in memory */
213                 wmb();
214                 return -ENOSPC;
215         }
216
217         qhdr->tx_req = 0;
218         /* ensure tx_req is updated in memory */
219         wmb();
220
221         new_wr_idx = wr_idx + dwords;
222         wr_ptr = (u32 *)(queue->qmem.kva + (wr_idx << 2));
223         if (new_wr_idx < qsize) {
224                 memcpy(wr_ptr, packet, dwords << 2);
225         } else {
226                 size_t len;
227
228                 new_wr_idx -= qsize;
229                 len = (dwords - new_wr_idx) << 2;
230                 memcpy(wr_ptr, packet, len);
231                 memcpy(queue->qmem.kva, packet + len, new_wr_idx << 2);
232         }
233
234         /* make sure packet is written before updating the write index */
235         wmb();
236
237         qhdr->write_idx = new_wr_idx;
238         *rx_req = qhdr->rx_req ? 1 : 0;
239
240         /* make sure write index is updated before an interrupt is raised */
241         mb();
242
243         return 0;
244 }
245
246 static int venus_read_queue(struct venus_hfi_device *hdev,
247                             struct iface_queue *queue, void *pkt, u32 *tx_req)
248 {
249         struct hfi_queue_header *qhdr;
250         u32 dwords, new_rd_idx;
251         u32 rd_idx, wr_idx, type, qsize;
252         u32 *rd_ptr;
253         u32 recv_request = 0;
254         int ret = 0;
255
256         if (!queue->qmem.kva)
257                 return -EINVAL;
258
259         qhdr = queue->qhdr;
260         if (!qhdr)
261                 return -EINVAL;
262
263         type = qhdr->type;
264         rd_idx = qhdr->read_idx;
265         wr_idx = qhdr->write_idx;
266         qsize = qhdr->q_size;
267
268         /* make sure data is valid before using it */
269         rmb();
270
271         /*
272          * Do not set receive request for debug queue, if set, Venus generates
273          * interrupt for debug messages even when there is no response message
274          * available. In general debug queue will not become full as it is being
275          * emptied out for every interrupt from Venus. Venus will anyway
276          * generates interrupt if it is full.
277          */
278         if (type & HFI_CTRL_TO_HOST_MSG_Q)
279                 recv_request = 1;
280
281         if (rd_idx == wr_idx) {
282                 qhdr->rx_req = recv_request;
283                 *tx_req = 0;
284                 /* update rx_req field in memory */
285                 wmb();
286                 return -ENODATA;
287         }
288
289         rd_ptr = (u32 *)(queue->qmem.kva + (rd_idx << 2));
290         dwords = *rd_ptr >> 2;
291         if (!dwords)
292                 return -EINVAL;
293
294         new_rd_idx = rd_idx + dwords;
295         if (((dwords << 2) <= IFACEQ_VAR_HUGE_PKT_SIZE) && rd_idx <= qsize) {
296                 if (new_rd_idx < qsize) {
297                         memcpy(pkt, rd_ptr, dwords << 2);
298                 } else {
299                         size_t len;
300
301                         new_rd_idx -= qsize;
302                         len = (dwords - new_rd_idx) << 2;
303                         memcpy(pkt, rd_ptr, len);
304                         memcpy(pkt + len, queue->qmem.kva, new_rd_idx << 2);
305                 }
306         } else {
307                 /* bad packet received, dropping */
308                 new_rd_idx = qhdr->write_idx;
309                 ret = -EBADMSG;
310         }
311
312         /* ensure the packet is read before updating read index */
313         rmb();
314
315         qhdr->read_idx = new_rd_idx;
316         /* ensure updating read index */
317         wmb();
318
319         rd_idx = qhdr->read_idx;
320         wr_idx = qhdr->write_idx;
321         /* ensure rd/wr indices are read from memory */
322         rmb();
323
324         if (rd_idx != wr_idx)
325                 qhdr->rx_req = 0;
326         else
327                 qhdr->rx_req = recv_request;
328
329         *tx_req = qhdr->tx_req ? 1 : 0;
330
331         /* ensure rx_req is stored to memory and tx_req is loaded from memory */
332         mb();
333
334         venus_dump_packet(hdev, pkt);
335
336         return ret;
337 }
338
339 static int venus_alloc(struct venus_hfi_device *hdev, struct mem_desc *desc,
340                        u32 size)
341 {
342         struct device *dev = hdev->core->dev;
343
344         desc->attrs = DMA_ATTR_WRITE_COMBINE;
345         desc->size = ALIGN(size, SZ_4K);
346
347         desc->kva = dma_alloc_attrs(dev, desc->size, &desc->da, GFP_KERNEL,
348                                     desc->attrs);
349         if (!desc->kva)
350                 return -ENOMEM;
351
352         return 0;
353 }
354
355 static void venus_free(struct venus_hfi_device *hdev, struct mem_desc *mem)
356 {
357         struct device *dev = hdev->core->dev;
358
359         dma_free_attrs(dev, mem->size, mem->kva, mem->da, mem->attrs);
360 }
361
362 static void venus_writel(struct venus_hfi_device *hdev, u32 reg, u32 value)
363 {
364         writel(value, hdev->core->base + reg);
365 }
366
367 static u32 venus_readl(struct venus_hfi_device *hdev, u32 reg)
368 {
369         return readl(hdev->core->base + reg);
370 }
371
372 static void venus_set_registers(struct venus_hfi_device *hdev)
373 {
374         const struct venus_resources *res = hdev->core->res;
375         const struct reg_val *tbl = res->reg_tbl;
376         unsigned int count = res->reg_tbl_size;
377         unsigned int i;
378
379         for (i = 0; i < count; i++)
380                 venus_writel(hdev, tbl[i].reg, tbl[i].value);
381 }
382
383 static void venus_soft_int(struct venus_hfi_device *hdev)
384 {
385         venus_writel(hdev, CPU_IC_SOFTINT, BIT(CPU_IC_SOFTINT_H2A_SHIFT));
386 }
387
388 static int venus_iface_cmdq_write_nolock(struct venus_hfi_device *hdev,
389                                          void *pkt)
390 {
391         struct device *dev = hdev->core->dev;
392         struct hfi_pkt_hdr *cmd_packet;
393         struct iface_queue *queue;
394         u32 rx_req;
395         int ret;
396
397         if (!venus_is_valid_state(hdev))
398                 return -EINVAL;
399
400         cmd_packet = (struct hfi_pkt_hdr *)pkt;
401         hdev->last_packet_type = cmd_packet->pkt_type;
402
403         queue = &hdev->queues[IFACEQ_CMD_IDX];
404
405         ret = venus_write_queue(hdev, queue, pkt, &rx_req);
406         if (ret) {
407                 dev_err(dev, "write to iface cmd queue failed (%d)\n", ret);
408                 return ret;
409         }
410
411         if (rx_req)
412                 venus_soft_int(hdev);
413
414         return 0;
415 }
416
417 static int venus_iface_cmdq_write(struct venus_hfi_device *hdev, void *pkt)
418 {
419         int ret;
420
421         mutex_lock(&hdev->lock);
422         ret = venus_iface_cmdq_write_nolock(hdev, pkt);
423         mutex_unlock(&hdev->lock);
424
425         return ret;
426 }
427
428 static int venus_hfi_core_set_resource(struct venus_core *core, u32 id,
429                                        u32 size, u32 addr, void *cookie)
430 {
431         struct venus_hfi_device *hdev = to_hfi_priv(core);
432         struct hfi_sys_set_resource_pkt *pkt;
433         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
434         int ret;
435
436         if (id == VIDC_RESOURCE_NONE)
437                 return 0;
438
439         pkt = (struct hfi_sys_set_resource_pkt *)packet;
440
441         ret = pkt_sys_set_resource(pkt, id, size, addr, cookie);
442         if (ret)
443                 return ret;
444
445         ret = venus_iface_cmdq_write(hdev, pkt);
446         if (ret)
447                 return ret;
448
449         return 0;
450 }
451
452 static int venus_boot_core(struct venus_hfi_device *hdev)
453 {
454         struct device *dev = hdev->core->dev;
455         static const unsigned int max_tries = 100;
456         u32 ctrl_status = 0;
457         unsigned int count = 0;
458         int ret = 0;
459
460         venus_writel(hdev, VIDC_CTRL_INIT, BIT(VIDC_CTRL_INIT_CTRL_SHIFT));
461         venus_writel(hdev, WRAPPER_INTR_MASK, WRAPPER_INTR_MASK_A2HVCODEC_MASK);
462         venus_writel(hdev, CPU_CS_SCIACMDARG3, 1);
463
464         while (!ctrl_status && count < max_tries) {
465                 ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
466                 if ((ctrl_status & CPU_CS_SCIACMDARG0_ERROR_STATUS_MASK) == 4) {
467                         dev_err(dev, "invalid setting for UC_REGION\n");
468                         ret = -EINVAL;
469                         break;
470                 }
471
472                 usleep_range(500, 1000);
473                 count++;
474         }
475
476         if (count >= max_tries)
477                 ret = -ETIMEDOUT;
478
479         return ret;
480 }
481
482 static u32 venus_hwversion(struct venus_hfi_device *hdev)
483 {
484         struct device *dev = hdev->core->dev;
485         u32 ver = venus_readl(hdev, WRAPPER_HW_VERSION);
486         u32 major, minor, step;
487
488         major = ver & WRAPPER_HW_VERSION_MAJOR_VERSION_MASK;
489         major = major >> WRAPPER_HW_VERSION_MAJOR_VERSION_SHIFT;
490         minor = ver & WRAPPER_HW_VERSION_MINOR_VERSION_MASK;
491         minor = minor >> WRAPPER_HW_VERSION_MINOR_VERSION_SHIFT;
492         step = ver & WRAPPER_HW_VERSION_STEP_VERSION_MASK;
493
494         dev_dbg(dev, "venus hw version %x.%x.%x\n", major, minor, step);
495
496         return major;
497 }
498
499 static int venus_run(struct venus_hfi_device *hdev)
500 {
501         struct device *dev = hdev->core->dev;
502         int ret;
503
504         /*
505          * Re-program all of the registers that get reset as a result of
506          * regulator_disable() and _enable()
507          */
508         venus_set_registers(hdev);
509
510         venus_writel(hdev, UC_REGION_ADDR, hdev->ifaceq_table.da);
511         venus_writel(hdev, UC_REGION_SIZE, SHARED_QSIZE);
512         venus_writel(hdev, CPU_CS_SCIACMDARG2, hdev->ifaceq_table.da);
513         venus_writel(hdev, CPU_CS_SCIACMDARG1, 0x01);
514         if (hdev->sfr.da)
515                 venus_writel(hdev, SFR_ADDR, hdev->sfr.da);
516
517         ret = venus_boot_core(hdev);
518         if (ret) {
519                 dev_err(dev, "failed to reset venus core\n");
520                 return ret;
521         }
522
523         venus_hwversion(hdev);
524
525         return 0;
526 }
527
528 static int venus_halt_axi(struct venus_hfi_device *hdev)
529 {
530         void __iomem *base = hdev->core->base;
531         struct device *dev = hdev->core->dev;
532         u32 val;
533         int ret;
534
535         if (IS_V4(hdev->core)) {
536                 val = venus_readl(hdev, WRAPPER_CPU_AXI_HALT);
537                 val |= WRAPPER_CPU_AXI_HALT_HALT;
538                 venus_writel(hdev, WRAPPER_CPU_AXI_HALT, val);
539
540                 ret = readl_poll_timeout(base + WRAPPER_CPU_AXI_HALT_STATUS,
541                                          val,
542                                          val & WRAPPER_CPU_AXI_HALT_STATUS_IDLE,
543                                          POLL_INTERVAL_US,
544                                          VBIF_AXI_HALT_ACK_TIMEOUT_US);
545                 if (ret) {
546                         dev_err(dev, "AXI bus port halt timeout\n");
547                         return ret;
548                 }
549
550                 return 0;
551         }
552
553         /* Halt AXI and AXI IMEM VBIF Access */
554         val = venus_readl(hdev, VBIF_AXI_HALT_CTRL0);
555         val |= VBIF_AXI_HALT_CTRL0_HALT_REQ;
556         venus_writel(hdev, VBIF_AXI_HALT_CTRL0, val);
557
558         /* Request for AXI bus port halt */
559         ret = readl_poll_timeout(base + VBIF_AXI_HALT_CTRL1, val,
560                                  val & VBIF_AXI_HALT_CTRL1_HALT_ACK,
561                                  POLL_INTERVAL_US,
562                                  VBIF_AXI_HALT_ACK_TIMEOUT_US);
563         if (ret) {
564                 dev_err(dev, "AXI bus port halt timeout\n");
565                 return ret;
566         }
567
568         return 0;
569 }
570
571 static int venus_power_off(struct venus_hfi_device *hdev)
572 {
573         int ret;
574
575         if (!hdev->power_enabled)
576                 return 0;
577
578         ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
579         if (ret)
580                 return ret;
581
582         ret = venus_halt_axi(hdev);
583         if (ret)
584                 return ret;
585
586         hdev->power_enabled = false;
587
588         return 0;
589 }
590
591 static int venus_power_on(struct venus_hfi_device *hdev)
592 {
593         int ret;
594
595         if (hdev->power_enabled)
596                 return 0;
597
598         ret = qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_RESUME, 0);
599         if (ret)
600                 goto err;
601
602         ret = venus_run(hdev);
603         if (ret)
604                 goto err_suspend;
605
606         hdev->power_enabled = true;
607
608         return 0;
609
610 err_suspend:
611         qcom_scm_set_remote_state(TZBSP_VIDEO_STATE_SUSPEND, 0);
612 err:
613         hdev->power_enabled = false;
614         return ret;
615 }
616
617 static int venus_iface_msgq_read_nolock(struct venus_hfi_device *hdev,
618                                         void *pkt)
619 {
620         struct iface_queue *queue;
621         u32 tx_req;
622         int ret;
623
624         if (!venus_is_valid_state(hdev))
625                 return -EINVAL;
626
627         queue = &hdev->queues[IFACEQ_MSG_IDX];
628
629         ret = venus_read_queue(hdev, queue, pkt, &tx_req);
630         if (ret)
631                 return ret;
632
633         if (tx_req)
634                 venus_soft_int(hdev);
635
636         return 0;
637 }
638
639 static int venus_iface_msgq_read(struct venus_hfi_device *hdev, void *pkt)
640 {
641         int ret;
642
643         mutex_lock(&hdev->lock);
644         ret = venus_iface_msgq_read_nolock(hdev, pkt);
645         mutex_unlock(&hdev->lock);
646
647         return ret;
648 }
649
650 static int venus_iface_dbgq_read_nolock(struct venus_hfi_device *hdev,
651                                         void *pkt)
652 {
653         struct iface_queue *queue;
654         u32 tx_req;
655         int ret;
656
657         ret = venus_is_valid_state(hdev);
658         if (!ret)
659                 return -EINVAL;
660
661         queue = &hdev->queues[IFACEQ_DBG_IDX];
662
663         ret = venus_read_queue(hdev, queue, pkt, &tx_req);
664         if (ret)
665                 return ret;
666
667         if (tx_req)
668                 venus_soft_int(hdev);
669
670         return 0;
671 }
672
673 static int venus_iface_dbgq_read(struct venus_hfi_device *hdev, void *pkt)
674 {
675         int ret;
676
677         if (!pkt)
678                 return -EINVAL;
679
680         mutex_lock(&hdev->lock);
681         ret = venus_iface_dbgq_read_nolock(hdev, pkt);
682         mutex_unlock(&hdev->lock);
683
684         return ret;
685 }
686
687 static void venus_set_qhdr_defaults(struct hfi_queue_header *qhdr)
688 {
689         qhdr->status = 1;
690         qhdr->type = IFACEQ_DFLT_QHDR;
691         qhdr->q_size = IFACEQ_QUEUE_SIZE / 4;
692         qhdr->pkt_size = 0;
693         qhdr->rx_wm = 1;
694         qhdr->tx_wm = 1;
695         qhdr->rx_req = 1;
696         qhdr->tx_req = 0;
697         qhdr->rx_irq_status = 0;
698         qhdr->tx_irq_status = 0;
699         qhdr->read_idx = 0;
700         qhdr->write_idx = 0;
701 }
702
703 static void venus_interface_queues_release(struct venus_hfi_device *hdev)
704 {
705         mutex_lock(&hdev->lock);
706
707         venus_free(hdev, &hdev->ifaceq_table);
708         venus_free(hdev, &hdev->sfr);
709
710         memset(hdev->queues, 0, sizeof(hdev->queues));
711         memset(&hdev->ifaceq_table, 0, sizeof(hdev->ifaceq_table));
712         memset(&hdev->sfr, 0, sizeof(hdev->sfr));
713
714         mutex_unlock(&hdev->lock);
715 }
716
717 static int venus_interface_queues_init(struct venus_hfi_device *hdev)
718 {
719         struct hfi_queue_table_header *tbl_hdr;
720         struct iface_queue *queue;
721         struct hfi_sfr *sfr;
722         struct mem_desc desc = {0};
723         unsigned int offset;
724         unsigned int i;
725         int ret;
726
727         ret = venus_alloc(hdev, &desc, ALIGNED_QUEUE_SIZE);
728         if (ret)
729                 return ret;
730
731         hdev->ifaceq_table = desc;
732         offset = IFACEQ_TABLE_SIZE;
733
734         for (i = 0; i < IFACEQ_NUM; i++) {
735                 queue = &hdev->queues[i];
736                 queue->qmem.da = desc.da + offset;
737                 queue->qmem.kva = desc.kva + offset;
738                 queue->qmem.size = IFACEQ_QUEUE_SIZE;
739                 offset += queue->qmem.size;
740                 queue->qhdr =
741                         IFACEQ_GET_QHDR_START_ADDR(hdev->ifaceq_table.kva, i);
742
743                 venus_set_qhdr_defaults(queue->qhdr);
744
745                 queue->qhdr->start_addr = queue->qmem.da;
746
747                 if (i == IFACEQ_CMD_IDX)
748                         queue->qhdr->type |= HFI_HOST_TO_CTRL_CMD_Q;
749                 else if (i == IFACEQ_MSG_IDX)
750                         queue->qhdr->type |= HFI_CTRL_TO_HOST_MSG_Q;
751                 else if (i == IFACEQ_DBG_IDX)
752                         queue->qhdr->type |= HFI_CTRL_TO_HOST_DBG_Q;
753         }
754
755         tbl_hdr = hdev->ifaceq_table.kva;
756         tbl_hdr->version = 0;
757         tbl_hdr->size = IFACEQ_TABLE_SIZE;
758         tbl_hdr->qhdr0_offset = sizeof(struct hfi_queue_table_header);
759         tbl_hdr->qhdr_size = sizeof(struct hfi_queue_header);
760         tbl_hdr->num_q = IFACEQ_NUM;
761         tbl_hdr->num_active_q = IFACEQ_NUM;
762
763         /*
764          * Set receive request to zero on debug queue as there is no
765          * need of interrupt from video hardware for debug messages
766          */
767         queue = &hdev->queues[IFACEQ_DBG_IDX];
768         queue->qhdr->rx_req = 0;
769
770         ret = venus_alloc(hdev, &desc, ALIGNED_SFR_SIZE);
771         if (ret) {
772                 hdev->sfr.da = 0;
773         } else {
774                 hdev->sfr = desc;
775                 sfr = hdev->sfr.kva;
776                 sfr->buf_size = ALIGNED_SFR_SIZE;
777         }
778
779         /* ensure table and queue header structs are settled in memory */
780         wmb();
781
782         return 0;
783 }
784
785 static int venus_sys_set_debug(struct venus_hfi_device *hdev, u32 debug)
786 {
787         struct hfi_sys_set_property_pkt *pkt;
788         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
789         int ret;
790
791         pkt = (struct hfi_sys_set_property_pkt *)packet;
792
793         pkt_sys_debug_config(pkt, HFI_DEBUG_MODE_QUEUE, debug);
794
795         ret = venus_iface_cmdq_write(hdev, pkt);
796         if (ret)
797                 return ret;
798
799         return 0;
800 }
801
802 static int venus_sys_set_coverage(struct venus_hfi_device *hdev, u32 mode)
803 {
804         struct hfi_sys_set_property_pkt *pkt;
805         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
806         int ret;
807
808         pkt = (struct hfi_sys_set_property_pkt *)packet;
809
810         pkt_sys_coverage_config(pkt, mode);
811
812         ret = venus_iface_cmdq_write(hdev, pkt);
813         if (ret)
814                 return ret;
815
816         return 0;
817 }
818
819 static int venus_sys_set_idle_message(struct venus_hfi_device *hdev,
820                                       bool enable)
821 {
822         struct hfi_sys_set_property_pkt *pkt;
823         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
824         int ret;
825
826         if (!enable)
827                 return 0;
828
829         pkt = (struct hfi_sys_set_property_pkt *)packet;
830
831         pkt_sys_idle_indicator(pkt, enable);
832
833         ret = venus_iface_cmdq_write(hdev, pkt);
834         if (ret)
835                 return ret;
836
837         return 0;
838 }
839
840 static int venus_sys_set_power_control(struct venus_hfi_device *hdev,
841                                        bool enable)
842 {
843         struct hfi_sys_set_property_pkt *pkt;
844         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
845         int ret;
846
847         pkt = (struct hfi_sys_set_property_pkt *)packet;
848
849         pkt_sys_power_control(pkt, enable);
850
851         ret = venus_iface_cmdq_write(hdev, pkt);
852         if (ret)
853                 return ret;
854
855         return 0;
856 }
857
858 static int venus_get_queue_size(struct venus_hfi_device *hdev,
859                                 unsigned int index)
860 {
861         struct hfi_queue_header *qhdr;
862
863         if (index >= IFACEQ_NUM)
864                 return -EINVAL;
865
866         qhdr = hdev->queues[index].qhdr;
867         if (!qhdr)
868                 return -EINVAL;
869
870         return abs(qhdr->read_idx - qhdr->write_idx);
871 }
872
873 static int venus_sys_set_default_properties(struct venus_hfi_device *hdev)
874 {
875         struct device *dev = hdev->core->dev;
876         int ret;
877
878         ret = venus_sys_set_debug(hdev, venus_fw_debug);
879         if (ret)
880                 dev_warn(dev, "setting fw debug msg ON failed (%d)\n", ret);
881
882         /*
883          * Idle indicator is disabled by default on some 4xx firmware versions,
884          * enable it explicitly in order to make suspend functional by checking
885          * WFI (wait-for-interrupt) bit.
886          */
887         if (IS_V4(hdev->core))
888                 venus_sys_idle_indicator = true;
889
890         ret = venus_sys_set_idle_message(hdev, venus_sys_idle_indicator);
891         if (ret)
892                 dev_warn(dev, "setting idle response ON failed (%d)\n", ret);
893
894         ret = venus_sys_set_power_control(hdev, venus_fw_low_power_mode);
895         if (ret)
896                 dev_warn(dev, "setting hw power collapse ON failed (%d)\n",
897                          ret);
898
899         return ret;
900 }
901
902 static int venus_session_cmd(struct venus_inst *inst, u32 pkt_type)
903 {
904         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
905         struct hfi_session_pkt pkt;
906
907         pkt_session_cmd(&pkt, pkt_type, inst);
908
909         return venus_iface_cmdq_write(hdev, &pkt);
910 }
911
912 static void venus_flush_debug_queue(struct venus_hfi_device *hdev)
913 {
914         struct device *dev = hdev->core->dev;
915         void *packet = hdev->dbg_buf;
916
917         while (!venus_iface_dbgq_read(hdev, packet)) {
918                 struct hfi_msg_sys_coverage_pkt *pkt = packet;
919
920                 if (pkt->hdr.pkt_type != HFI_MSG_SYS_COV) {
921                         struct hfi_msg_sys_debug_pkt *pkt = packet;
922
923                         dev_dbg(dev, "%s", pkt->msg_data);
924                 }
925         }
926 }
927
928 static int venus_prepare_power_collapse(struct venus_hfi_device *hdev,
929                                         bool wait)
930 {
931         unsigned long timeout = msecs_to_jiffies(venus_hw_rsp_timeout);
932         struct hfi_sys_pc_prep_pkt pkt;
933         int ret;
934
935         init_completion(&hdev->pwr_collapse_prep);
936
937         pkt_sys_pc_prep(&pkt);
938
939         ret = venus_iface_cmdq_write(hdev, &pkt);
940         if (ret)
941                 return ret;
942
943         if (!wait)
944                 return 0;
945
946         ret = wait_for_completion_timeout(&hdev->pwr_collapse_prep, timeout);
947         if (!ret) {
948                 venus_flush_debug_queue(hdev);
949                 return -ETIMEDOUT;
950         }
951
952         return 0;
953 }
954
955 static int venus_are_queues_empty(struct venus_hfi_device *hdev)
956 {
957         int ret1, ret2;
958
959         ret1 = venus_get_queue_size(hdev, IFACEQ_MSG_IDX);
960         if (ret1 < 0)
961                 return ret1;
962
963         ret2 = venus_get_queue_size(hdev, IFACEQ_CMD_IDX);
964         if (ret2 < 0)
965                 return ret2;
966
967         if (!ret1 && !ret2)
968                 return 1;
969
970         return 0;
971 }
972
973 static void venus_sfr_print(struct venus_hfi_device *hdev)
974 {
975         struct device *dev = hdev->core->dev;
976         struct hfi_sfr *sfr = hdev->sfr.kva;
977         void *p;
978
979         if (!sfr)
980                 return;
981
982         p = memchr(sfr->data, '\0', sfr->buf_size);
983         /*
984          * SFR isn't guaranteed to be NULL terminated since SYS_ERROR indicates
985          * that Venus is in the process of crashing.
986          */
987         if (!p)
988                 sfr->data[sfr->buf_size - 1] = '\0';
989
990         dev_err_ratelimited(dev, "SFR message from FW: %s\n", sfr->data);
991 }
992
993 static void venus_process_msg_sys_error(struct venus_hfi_device *hdev,
994                                         void *packet)
995 {
996         struct hfi_msg_event_notify_pkt *event_pkt = packet;
997
998         if (event_pkt->event_id != HFI_EVENT_SYS_ERROR)
999                 return;
1000
1001         venus_set_state(hdev, VENUS_STATE_DEINIT);
1002
1003         /*
1004          * Once SYS_ERROR received from HW, it is safe to halt the AXI.
1005          * With SYS_ERROR, Venus FW may have crashed and HW might be
1006          * active and causing unnecessary transactions. Hence it is
1007          * safe to stop all AXI transactions from venus subsystem.
1008          */
1009         venus_halt_axi(hdev);
1010         venus_sfr_print(hdev);
1011 }
1012
1013 static irqreturn_t venus_isr_thread(struct venus_core *core)
1014 {
1015         struct venus_hfi_device *hdev = to_hfi_priv(core);
1016         const struct venus_resources *res;
1017         void *pkt;
1018         u32 msg_ret;
1019
1020         if (!hdev)
1021                 return IRQ_NONE;
1022
1023         res = hdev->core->res;
1024         pkt = hdev->pkt_buf;
1025
1026         if (hdev->irq_status & WRAPPER_INTR_STATUS_A2HWD_MASK) {
1027                 venus_sfr_print(hdev);
1028                 hfi_process_watchdog_timeout(core);
1029         }
1030
1031         while (!venus_iface_msgq_read(hdev, pkt)) {
1032                 msg_ret = hfi_process_msg_packet(core, pkt);
1033                 switch (msg_ret) {
1034                 case HFI_MSG_EVENT_NOTIFY:
1035                         venus_process_msg_sys_error(hdev, pkt);
1036                         break;
1037                 case HFI_MSG_SYS_INIT:
1038                         venus_hfi_core_set_resource(core, res->vmem_id,
1039                                                     res->vmem_size,
1040                                                     res->vmem_addr,
1041                                                     hdev);
1042                         break;
1043                 case HFI_MSG_SYS_RELEASE_RESOURCE:
1044                         complete(&hdev->release_resource);
1045                         break;
1046                 case HFI_MSG_SYS_PC_PREP:
1047                         complete(&hdev->pwr_collapse_prep);
1048                         break;
1049                 default:
1050                         break;
1051                 }
1052         }
1053
1054         venus_flush_debug_queue(hdev);
1055
1056         return IRQ_HANDLED;
1057 }
1058
1059 static irqreturn_t venus_isr(struct venus_core *core)
1060 {
1061         struct venus_hfi_device *hdev = to_hfi_priv(core);
1062         u32 status;
1063
1064         if (!hdev)
1065                 return IRQ_NONE;
1066
1067         status = venus_readl(hdev, WRAPPER_INTR_STATUS);
1068
1069         if (status & WRAPPER_INTR_STATUS_A2H_MASK ||
1070             status & WRAPPER_INTR_STATUS_A2HWD_MASK ||
1071             status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK)
1072                 hdev->irq_status = status;
1073
1074         venus_writel(hdev, CPU_CS_A2HSOFTINTCLR, 1);
1075         venus_writel(hdev, WRAPPER_INTR_CLEAR, status);
1076
1077         return IRQ_WAKE_THREAD;
1078 }
1079
1080 static int venus_core_init(struct venus_core *core)
1081 {
1082         struct venus_hfi_device *hdev = to_hfi_priv(core);
1083         struct device *dev = core->dev;
1084         struct hfi_sys_get_property_pkt version_pkt;
1085         struct hfi_sys_init_pkt pkt;
1086         int ret;
1087
1088         pkt_sys_init(&pkt, HFI_VIDEO_ARCH_OX);
1089
1090         venus_set_state(hdev, VENUS_STATE_INIT);
1091
1092         ret = venus_iface_cmdq_write(hdev, &pkt);
1093         if (ret)
1094                 return ret;
1095
1096         pkt_sys_image_version(&version_pkt);
1097
1098         ret = venus_iface_cmdq_write(hdev, &version_pkt);
1099         if (ret)
1100                 dev_warn(dev, "failed to send image version pkt to fw\n");
1101
1102         ret = venus_sys_set_default_properties(hdev);
1103         if (ret)
1104                 return ret;
1105
1106         return 0;
1107 }
1108
1109 static int venus_core_deinit(struct venus_core *core)
1110 {
1111         struct venus_hfi_device *hdev = to_hfi_priv(core);
1112
1113         venus_set_state(hdev, VENUS_STATE_DEINIT);
1114         hdev->suspended = true;
1115         hdev->power_enabled = false;
1116
1117         return 0;
1118 }
1119
1120 static int venus_core_ping(struct venus_core *core, u32 cookie)
1121 {
1122         struct venus_hfi_device *hdev = to_hfi_priv(core);
1123         struct hfi_sys_ping_pkt pkt;
1124
1125         pkt_sys_ping(&pkt, cookie);
1126
1127         return venus_iface_cmdq_write(hdev, &pkt);
1128 }
1129
1130 static int venus_core_trigger_ssr(struct venus_core *core, u32 trigger_type)
1131 {
1132         struct venus_hfi_device *hdev = to_hfi_priv(core);
1133         struct hfi_sys_test_ssr_pkt pkt;
1134         int ret;
1135
1136         ret = pkt_sys_ssr_cmd(&pkt, trigger_type);
1137         if (ret)
1138                 return ret;
1139
1140         return venus_iface_cmdq_write(hdev, &pkt);
1141 }
1142
1143 static int venus_session_init(struct venus_inst *inst, u32 session_type,
1144                               u32 codec)
1145 {
1146         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1147         struct hfi_session_init_pkt pkt;
1148         int ret;
1149
1150         ret = pkt_session_init(&pkt, inst, session_type, codec);
1151         if (ret)
1152                 goto err;
1153
1154         ret = venus_iface_cmdq_write(hdev, &pkt);
1155         if (ret)
1156                 goto err;
1157
1158         return 0;
1159
1160 err:
1161         venus_flush_debug_queue(hdev);
1162         return ret;
1163 }
1164
1165 static int venus_session_end(struct venus_inst *inst)
1166 {
1167         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1168         struct device *dev = hdev->core->dev;
1169
1170         if (venus_fw_coverage) {
1171                 if (venus_sys_set_coverage(hdev, venus_fw_coverage))
1172                         dev_warn(dev, "fw coverage msg ON failed\n");
1173         }
1174
1175         return venus_session_cmd(inst, HFI_CMD_SYS_SESSION_END);
1176 }
1177
1178 static int venus_session_abort(struct venus_inst *inst)
1179 {
1180         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1181
1182         venus_flush_debug_queue(hdev);
1183
1184         return venus_session_cmd(inst, HFI_CMD_SYS_SESSION_ABORT);
1185 }
1186
1187 static int venus_session_flush(struct venus_inst *inst, u32 flush_mode)
1188 {
1189         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1190         struct hfi_session_flush_pkt pkt;
1191         int ret;
1192
1193         ret = pkt_session_flush(&pkt, inst, flush_mode);
1194         if (ret)
1195                 return ret;
1196
1197         return venus_iface_cmdq_write(hdev, &pkt);
1198 }
1199
1200 static int venus_session_start(struct venus_inst *inst)
1201 {
1202         return venus_session_cmd(inst, HFI_CMD_SESSION_START);
1203 }
1204
1205 static int venus_session_stop(struct venus_inst *inst)
1206 {
1207         return venus_session_cmd(inst, HFI_CMD_SESSION_STOP);
1208 }
1209
1210 static int venus_session_continue(struct venus_inst *inst)
1211 {
1212         return venus_session_cmd(inst, HFI_CMD_SESSION_CONTINUE);
1213 }
1214
1215 static int venus_session_etb(struct venus_inst *inst,
1216                              struct hfi_frame_data *in_frame)
1217 {
1218         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1219         u32 session_type = inst->session_type;
1220         int ret;
1221
1222         if (session_type == VIDC_SESSION_TYPE_DEC) {
1223                 struct hfi_session_empty_buffer_compressed_pkt pkt;
1224
1225                 ret = pkt_session_etb_decoder(&pkt, inst, in_frame);
1226                 if (ret)
1227                         return ret;
1228
1229                 ret = venus_iface_cmdq_write(hdev, &pkt);
1230         } else if (session_type == VIDC_SESSION_TYPE_ENC) {
1231                 struct hfi_session_empty_buffer_uncompressed_plane0_pkt pkt;
1232
1233                 ret = pkt_session_etb_encoder(&pkt, inst, in_frame);
1234                 if (ret)
1235                         return ret;
1236
1237                 ret = venus_iface_cmdq_write(hdev, &pkt);
1238         } else {
1239                 ret = -EINVAL;
1240         }
1241
1242         return ret;
1243 }
1244
1245 static int venus_session_ftb(struct venus_inst *inst,
1246                              struct hfi_frame_data *out_frame)
1247 {
1248         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1249         struct hfi_session_fill_buffer_pkt pkt;
1250         int ret;
1251
1252         ret = pkt_session_ftb(&pkt, inst, out_frame);
1253         if (ret)
1254                 return ret;
1255
1256         return venus_iface_cmdq_write(hdev, &pkt);
1257 }
1258
1259 static int venus_session_set_buffers(struct venus_inst *inst,
1260                                      struct hfi_buffer_desc *bd)
1261 {
1262         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1263         struct hfi_session_set_buffers_pkt *pkt;
1264         u8 packet[IFACEQ_VAR_LARGE_PKT_SIZE];
1265         int ret;
1266
1267         if (bd->buffer_type == HFI_BUFFER_INPUT)
1268                 return 0;
1269
1270         pkt = (struct hfi_session_set_buffers_pkt *)packet;
1271
1272         ret = pkt_session_set_buffers(pkt, inst, bd);
1273         if (ret)
1274                 return ret;
1275
1276         return venus_iface_cmdq_write(hdev, pkt);
1277 }
1278
1279 static int venus_session_unset_buffers(struct venus_inst *inst,
1280                                        struct hfi_buffer_desc *bd)
1281 {
1282         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1283         struct hfi_session_release_buffer_pkt *pkt;
1284         u8 packet[IFACEQ_VAR_LARGE_PKT_SIZE];
1285         int ret;
1286
1287         if (bd->buffer_type == HFI_BUFFER_INPUT)
1288                 return 0;
1289
1290         pkt = (struct hfi_session_release_buffer_pkt *)packet;
1291
1292         ret = pkt_session_unset_buffers(pkt, inst, bd);
1293         if (ret)
1294                 return ret;
1295
1296         return venus_iface_cmdq_write(hdev, pkt);
1297 }
1298
1299 static int venus_session_load_res(struct venus_inst *inst)
1300 {
1301         return venus_session_cmd(inst, HFI_CMD_SESSION_LOAD_RESOURCES);
1302 }
1303
1304 static int venus_session_release_res(struct venus_inst *inst)
1305 {
1306         return venus_session_cmd(inst, HFI_CMD_SESSION_RELEASE_RESOURCES);
1307 }
1308
1309 static int venus_session_parse_seq_hdr(struct venus_inst *inst, u32 seq_hdr,
1310                                        u32 seq_hdr_len)
1311 {
1312         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1313         struct hfi_session_parse_sequence_header_pkt *pkt;
1314         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
1315         int ret;
1316
1317         pkt = (struct hfi_session_parse_sequence_header_pkt *)packet;
1318
1319         ret = pkt_session_parse_seq_header(pkt, inst, seq_hdr, seq_hdr_len);
1320         if (ret)
1321                 return ret;
1322
1323         ret = venus_iface_cmdq_write(hdev, pkt);
1324         if (ret)
1325                 return ret;
1326
1327         return 0;
1328 }
1329
1330 static int venus_session_get_seq_hdr(struct venus_inst *inst, u32 seq_hdr,
1331                                      u32 seq_hdr_len)
1332 {
1333         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1334         struct hfi_session_get_sequence_header_pkt *pkt;
1335         u8 packet[IFACEQ_VAR_SMALL_PKT_SIZE];
1336         int ret;
1337
1338         pkt = (struct hfi_session_get_sequence_header_pkt *)packet;
1339
1340         ret = pkt_session_get_seq_hdr(pkt, inst, seq_hdr, seq_hdr_len);
1341         if (ret)
1342                 return ret;
1343
1344         return venus_iface_cmdq_write(hdev, pkt);
1345 }
1346
1347 static int venus_session_set_property(struct venus_inst *inst, u32 ptype,
1348                                       void *pdata)
1349 {
1350         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1351         struct hfi_session_set_property_pkt *pkt;
1352         u8 packet[IFACEQ_VAR_LARGE_PKT_SIZE];
1353         int ret;
1354
1355         pkt = (struct hfi_session_set_property_pkt *)packet;
1356
1357         ret = pkt_session_set_property(pkt, inst, ptype, pdata);
1358         if (ret)
1359                 return ret;
1360
1361         return venus_iface_cmdq_write(hdev, pkt);
1362 }
1363
1364 static int venus_session_get_property(struct venus_inst *inst, u32 ptype)
1365 {
1366         struct venus_hfi_device *hdev = to_hfi_priv(inst->core);
1367         struct hfi_session_get_property_pkt pkt;
1368         int ret;
1369
1370         ret = pkt_session_get_property(&pkt, inst, ptype);
1371         if (ret)
1372                 return ret;
1373
1374         return venus_iface_cmdq_write(hdev, &pkt);
1375 }
1376
1377 static int venus_resume(struct venus_core *core)
1378 {
1379         struct venus_hfi_device *hdev = to_hfi_priv(core);
1380         int ret = 0;
1381
1382         mutex_lock(&hdev->lock);
1383
1384         if (!hdev->suspended)
1385                 goto unlock;
1386
1387         ret = venus_power_on(hdev);
1388
1389 unlock:
1390         if (!ret)
1391                 hdev->suspended = false;
1392
1393         mutex_unlock(&hdev->lock);
1394
1395         return ret;
1396 }
1397
1398 static int venus_suspend_1xx(struct venus_core *core)
1399 {
1400         struct venus_hfi_device *hdev = to_hfi_priv(core);
1401         struct device *dev = core->dev;
1402         u32 ctrl_status;
1403         int ret;
1404
1405         if (!hdev->power_enabled || hdev->suspended)
1406                 return 0;
1407
1408         mutex_lock(&hdev->lock);
1409         ret = venus_is_valid_state(hdev);
1410         mutex_unlock(&hdev->lock);
1411
1412         if (!ret) {
1413                 dev_err(dev, "bad state, cannot suspend\n");
1414                 return -EINVAL;
1415         }
1416
1417         ret = venus_prepare_power_collapse(hdev, true);
1418         if (ret) {
1419                 dev_err(dev, "prepare for power collapse fail (%d)\n", ret);
1420                 return ret;
1421         }
1422
1423         mutex_lock(&hdev->lock);
1424
1425         if (hdev->last_packet_type != HFI_CMD_SYS_PC_PREP) {
1426                 mutex_unlock(&hdev->lock);
1427                 return -EINVAL;
1428         }
1429
1430         ret = venus_are_queues_empty(hdev);
1431         if (ret < 0 || !ret) {
1432                 mutex_unlock(&hdev->lock);
1433                 return -EINVAL;
1434         }
1435
1436         ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
1437         if (!(ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)) {
1438                 mutex_unlock(&hdev->lock);
1439                 return -EINVAL;
1440         }
1441
1442         ret = venus_power_off(hdev);
1443         if (ret) {
1444                 mutex_unlock(&hdev->lock);
1445                 return ret;
1446         }
1447
1448         hdev->suspended = true;
1449
1450         mutex_unlock(&hdev->lock);
1451
1452         return 0;
1453 }
1454
1455 static bool venus_cpu_and_video_core_idle(struct venus_hfi_device *hdev)
1456 {
1457         u32 ctrl_status, cpu_status;
1458
1459         cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS);
1460         ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
1461
1462         if (cpu_status & WRAPPER_CPU_STATUS_WFI &&
1463             ctrl_status & CPU_CS_SCIACMDARG0_INIT_IDLE_MSG_MASK)
1464                 return true;
1465
1466         return false;
1467 }
1468
1469 static bool venus_cpu_idle_and_pc_ready(struct venus_hfi_device *hdev)
1470 {
1471         u32 ctrl_status, cpu_status;
1472
1473         cpu_status = venus_readl(hdev, WRAPPER_CPU_STATUS);
1474         ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
1475
1476         if (cpu_status & WRAPPER_CPU_STATUS_WFI &&
1477             ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)
1478                 return true;
1479
1480         return false;
1481 }
1482
1483 static int venus_suspend_3xx(struct venus_core *core)
1484 {
1485         struct venus_hfi_device *hdev = to_hfi_priv(core);
1486         struct device *dev = core->dev;
1487         u32 ctrl_status;
1488         bool val;
1489         int ret;
1490
1491         if (!hdev->power_enabled || hdev->suspended)
1492                 return 0;
1493
1494         mutex_lock(&hdev->lock);
1495         ret = venus_is_valid_state(hdev);
1496         mutex_unlock(&hdev->lock);
1497
1498         if (!ret) {
1499                 dev_err(dev, "bad state, cannot suspend\n");
1500                 return -EINVAL;
1501         }
1502
1503         ctrl_status = venus_readl(hdev, CPU_CS_SCIACMDARG0);
1504         if (ctrl_status & CPU_CS_SCIACMDARG0_PC_READY)
1505                 goto power_off;
1506
1507         /*
1508          * Power collapse sequence for Venus 3xx and 4xx versions:
1509          * 1. Check for ARM9 and video core to be idle by checking WFI bit
1510          *    (bit 0) in CPU status register and by checking Idle (bit 30) in
1511          *    Control status register for video core.
1512          * 2. Send a command to prepare for power collapse.
1513          * 3. Check for WFI and PC_READY bits.
1514          */
1515         ret = readx_poll_timeout(venus_cpu_and_video_core_idle, hdev, val, val,
1516                                  1500, 100 * 1500);
1517         if (ret)
1518                 return ret;
1519
1520         ret = venus_prepare_power_collapse(hdev, false);
1521         if (ret) {
1522                 dev_err(dev, "prepare for power collapse fail (%d)\n", ret);
1523                 return ret;
1524         }
1525
1526         ret = readx_poll_timeout(venus_cpu_idle_and_pc_ready, hdev, val, val,
1527                                  1500, 100 * 1500);
1528         if (ret)
1529                 return ret;
1530
1531 power_off:
1532         mutex_lock(&hdev->lock);
1533
1534         ret = venus_power_off(hdev);
1535         if (ret) {
1536                 dev_err(dev, "venus_power_off (%d)\n", ret);
1537                 mutex_unlock(&hdev->lock);
1538                 return ret;
1539         }
1540
1541         hdev->suspended = true;
1542
1543         mutex_unlock(&hdev->lock);
1544
1545         return 0;
1546 }
1547
1548 static int venus_suspend(struct venus_core *core)
1549 {
1550         if (IS_V3(core) || IS_V4(core))
1551                 return venus_suspend_3xx(core);
1552
1553         return venus_suspend_1xx(core);
1554 }
1555
1556 static const struct hfi_ops venus_hfi_ops = {
1557         .core_init                      = venus_core_init,
1558         .core_deinit                    = venus_core_deinit,
1559         .core_ping                      = venus_core_ping,
1560         .core_trigger_ssr               = venus_core_trigger_ssr,
1561
1562         .session_init                   = venus_session_init,
1563         .session_end                    = venus_session_end,
1564         .session_abort                  = venus_session_abort,
1565         .session_flush                  = venus_session_flush,
1566         .session_start                  = venus_session_start,
1567         .session_stop                   = venus_session_stop,
1568         .session_continue               = venus_session_continue,
1569         .session_etb                    = venus_session_etb,
1570         .session_ftb                    = venus_session_ftb,
1571         .session_set_buffers            = venus_session_set_buffers,
1572         .session_unset_buffers          = venus_session_unset_buffers,
1573         .session_load_res               = venus_session_load_res,
1574         .session_release_res            = venus_session_release_res,
1575         .session_parse_seq_hdr          = venus_session_parse_seq_hdr,
1576         .session_get_seq_hdr            = venus_session_get_seq_hdr,
1577         .session_set_property           = venus_session_set_property,
1578         .session_get_property           = venus_session_get_property,
1579
1580         .resume                         = venus_resume,
1581         .suspend                        = venus_suspend,
1582
1583         .isr                            = venus_isr,
1584         .isr_thread                     = venus_isr_thread,
1585 };
1586
1587 void venus_hfi_destroy(struct venus_core *core)
1588 {
1589         struct venus_hfi_device *hdev = to_hfi_priv(core);
1590
1591         venus_interface_queues_release(hdev);
1592         mutex_destroy(&hdev->lock);
1593         kfree(hdev);
1594         core->priv = NULL;
1595         core->ops = NULL;
1596 }
1597
1598 int venus_hfi_create(struct venus_core *core)
1599 {
1600         struct venus_hfi_device *hdev;
1601         int ret;
1602
1603         hdev = kzalloc(sizeof(*hdev), GFP_KERNEL);
1604         if (!hdev)
1605                 return -ENOMEM;
1606
1607         mutex_init(&hdev->lock);
1608
1609         hdev->core = core;
1610         hdev->suspended = true;
1611         core->priv = hdev;
1612         core->ops = &venus_hfi_ops;
1613         core->core_caps = ENC_ROTATION_CAPABILITY | ENC_SCALING_CAPABILITY |
1614                           ENC_DEINTERLACE_CAPABILITY |
1615                           DEC_MULTI_STREAM_CAPABILITY;
1616
1617         ret = venus_interface_queues_init(hdev);
1618         if (ret)
1619                 goto err_kfree;
1620
1621         return 0;
1622
1623 err_kfree:
1624         kfree(hdev);
1625         core->priv = NULL;
1626         core->ops = NULL;
1627         return ret;
1628 }