1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2018 Maxime Jourdan <maxi.jourdan@wanadoo.fr> 4 * 5 * VDEC_HEVC is a video decoding block that allows decoding of 6 * HEVC, VP9 7 */ 8 9 #include <linux/firmware.h> 10 #include <linux/clk.h> 11 12 #include "vdec_1.h" 13 #include "vdec_helpers.h" 14 #include "vdec_hevc.h" 15 #include "hevc_regs.h" 16 #include "dos_regs.h" 17 18 /* AO Registers */ 19 #define AO_RTI_GEN_PWR_SLEEP0 0xe8 20 #define AO_RTI_GEN_PWR_ISO0 0xec 21 #define GEN_PWR_VDEC_HEVC (BIT(7) | BIT(6)) 22 #define GEN_PWR_VDEC_HEVC_SM1 (BIT(2)) 23 24 #define MC_SIZE (4096 * 4) 25 26 static int vdec_hevc_load_firmware(struct amvdec_session *sess, 27 const char *fwname) 28 { 29 struct amvdec_core *core = sess->core; 30 struct device *dev = core->dev_dec; 31 const struct firmware *fw; 32 static void *mc_addr; 33 static dma_addr_t mc_addr_map; 34 int ret; 35 u32 i = 100; 36 37 ret = request_firmware(&fw, fwname, dev); 38 if (ret < 0) { 39 dev_err(dev, "Unable to request firmware %s\n", fwname); 40 return ret; 41 } 42 43 if (fw->size < MC_SIZE) { 44 dev_err(dev, "Firmware size %zu is too small. Expected %u.\n", 45 fw->size, MC_SIZE); 46 ret = -EINVAL; 47 goto release_firmware; 48 } 49 50 mc_addr = dma_alloc_coherent(core->dev, MC_SIZE, &mc_addr_map, 51 GFP_KERNEL); 52 if (!mc_addr) { 53 ret = -ENOMEM; 54 goto release_firmware; 55 } 56 57 memcpy(mc_addr, fw->data, MC_SIZE); 58 59 amvdec_write_dos(core, HEVC_MPSR, 0); 60 amvdec_write_dos(core, HEVC_CPSR, 0); 61 62 amvdec_write_dos(core, HEVC_IMEM_DMA_ADR, mc_addr_map); 63 amvdec_write_dos(core, HEVC_IMEM_DMA_COUNT, MC_SIZE / 4); 64 amvdec_write_dos(core, HEVC_IMEM_DMA_CTRL, (0x8000 | (7 << 16))); 65 66 while (i && (readl(core->dos_base + HEVC_IMEM_DMA_CTRL) & 0x8000)) 67 i--; 68 69 if (i == 0) { 70 dev_err(dev, "Firmware load fail (DMA hang?)\n"); 71 ret = -ENODEV; 72 } 73 74 dma_free_coherent(core->dev, MC_SIZE, mc_addr, mc_addr_map); 75 release_firmware: 76 release_firmware(fw); 77 return ret; 78 } 79 80 static void vdec_hevc_stbuf_init(struct amvdec_session *sess) 81 { 82 struct amvdec_core *core = sess->core; 83 84 amvdec_write_dos(core, HEVC_STREAM_CONTROL, 85 amvdec_read_dos(core, HEVC_STREAM_CONTROL) & ~1); 86 amvdec_write_dos(core, HEVC_STREAM_START_ADDR, sess->vififo_paddr); 87 amvdec_write_dos(core, HEVC_STREAM_END_ADDR, 88 sess->vififo_paddr + sess->vififo_size); 89 amvdec_write_dos(core, HEVC_STREAM_RD_PTR, sess->vififo_paddr); 90 amvdec_write_dos(core, HEVC_STREAM_WR_PTR, sess->vififo_paddr); 91 } 92 93 /* VDEC_HEVC specific ESPARSER configuration */ 94 static void vdec_hevc_conf_esparser(struct amvdec_session *sess) 95 { 96 struct amvdec_core *core = sess->core; 97 98 /* set vififo_vbuf_rp_sel=>vdec_hevc */ 99 amvdec_write_dos(core, DOS_GEN_CTRL0, 3 << 1); 100 amvdec_write_dos(core, HEVC_STREAM_CONTROL, 101 amvdec_read_dos(core, HEVC_STREAM_CONTROL) | BIT(3)); 102 amvdec_write_dos(core, HEVC_STREAM_CONTROL, 103 amvdec_read_dos(core, HEVC_STREAM_CONTROL) | 1); 104 amvdec_write_dos(core, HEVC_STREAM_FIFO_CTL, 105 amvdec_read_dos(core, HEVC_STREAM_FIFO_CTL) | BIT(29)); 106 } 107 108 static u32 vdec_hevc_vififo_level(struct amvdec_session *sess) 109 { 110 return readl_relaxed(sess->core->dos_base + HEVC_STREAM_LEVEL); 111 } 112 113 static int vdec_hevc_stop(struct amvdec_session *sess) 114 { 115 struct amvdec_core *core = sess->core; 116 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 117 118 /* Disable interrupt */ 119 amvdec_write_dos(core, HEVC_ASSIST_MBOX1_MASK, 0); 120 /* Disable firmware processor */ 121 amvdec_write_dos(core, HEVC_MPSR, 0); 122 123 if (sess->priv) 124 codec_ops->stop(sess); 125 126 /* Enable VDEC_HEVC Isolation */ 127 if (core->platform->revision == VDEC_REVISION_SM1) 128 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0, 129 GEN_PWR_VDEC_HEVC_SM1, 130 GEN_PWR_VDEC_HEVC_SM1); 131 else 132 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0, 133 0xc00, 0xc00); 134 135 /* VDEC_HEVC Memories */ 136 amvdec_write_dos(core, DOS_MEM_PD_HEVC, 0xffffffffUL); 137 138 if (core->platform->revision == VDEC_REVISION_SM1) 139 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, 140 GEN_PWR_VDEC_HEVC_SM1, 141 GEN_PWR_VDEC_HEVC_SM1); 142 else 143 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, 144 GEN_PWR_VDEC_HEVC, GEN_PWR_VDEC_HEVC); 145 146 clk_disable_unprepare(core->vdec_hevc_clk); 147 if (core->platform->revision == VDEC_REVISION_G12A || 148 core->platform->revision == VDEC_REVISION_SM1) 149 clk_disable_unprepare(core->vdec_hevcf_clk); 150 151 return 0; 152 } 153 154 static int vdec_hevc_start(struct amvdec_session *sess) 155 { 156 int ret; 157 struct amvdec_core *core = sess->core; 158 struct amvdec_codec_ops *codec_ops = sess->fmt_out->codec_ops; 159 160 if (core->platform->revision == VDEC_REVISION_G12A || 161 core->platform->revision == VDEC_REVISION_SM1) { 162 clk_set_rate(core->vdec_hevcf_clk, 666666666); 163 ret = clk_prepare_enable(core->vdec_hevcf_clk); 164 if (ret) 165 return ret; 166 } 167 168 clk_set_rate(core->vdec_hevc_clk, 666666666); 169 ret = clk_prepare_enable(core->vdec_hevc_clk); 170 if (ret) 171 return ret; 172 173 if (core->platform->revision == VDEC_REVISION_SM1) 174 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, 175 GEN_PWR_VDEC_HEVC_SM1, 0); 176 else 177 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_SLEEP0, 178 GEN_PWR_VDEC_HEVC, 0); 179 usleep_range(10, 20); 180 181 /* Reset VDEC_HEVC*/ 182 amvdec_write_dos(core, DOS_SW_RESET3, 0xffffffff); 183 amvdec_write_dos(core, DOS_SW_RESET3, 0x00000000); 184 185 amvdec_write_dos(core, DOS_GCLK_EN3, 0xffffffff); 186 187 /* VDEC_HEVC Memories */ 188 amvdec_write_dos(core, DOS_MEM_PD_HEVC, 0x00000000); 189 190 /* Remove VDEC_HEVC Isolation */ 191 if (core->platform->revision == VDEC_REVISION_SM1) 192 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0, 193 GEN_PWR_VDEC_HEVC_SM1, 0); 194 else 195 regmap_update_bits(core->regmap_ao, AO_RTI_GEN_PWR_ISO0, 196 0xc00, 0); 197 198 amvdec_write_dos(core, DOS_SW_RESET3, 0xffffffff); 199 amvdec_write_dos(core, DOS_SW_RESET3, 0x00000000); 200 201 vdec_hevc_stbuf_init(sess); 202 203 ret = vdec_hevc_load_firmware(sess, sess->fmt_out->firmware_path); 204 if (ret) 205 goto stop; 206 207 ret = codec_ops->start(sess); 208 if (ret) 209 goto stop; 210 211 amvdec_write_dos(core, DOS_SW_RESET3, BIT(12) | BIT(11)); 212 amvdec_write_dos(core, DOS_SW_RESET3, 0); 213 amvdec_read_dos(core, DOS_SW_RESET3); 214 215 amvdec_write_dos(core, HEVC_MPSR, 1); 216 /* Let the firmware settle */ 217 usleep_range(10, 20); 218 219 return 0; 220 221 stop: 222 vdec_hevc_stop(sess); 223 return ret; 224 } 225 226 struct amvdec_ops vdec_hevc_ops = { 227 .start = vdec_hevc_start, 228 .stop = vdec_hevc_stop, 229 .conf_esparser = vdec_hevc_conf_esparser, 230 .vififo_level = vdec_hevc_vififo_level, 231 }; 232