.. | .. |
---|
32 | 32 | #include <soc/rockchip/rockchip_ipa.h> |
---|
33 | 33 | #include <soc/rockchip/rockchip_opp_select.h> |
---|
34 | 34 | #include <soc/rockchip/rockchip_system_monitor.h> |
---|
| 35 | +#include <soc/rockchip/rockchip_iommu.h> |
---|
35 | 36 | |
---|
36 | 37 | #include "mpp_debug.h" |
---|
37 | 38 | #include "mpp_iommu.h" |
---|
.. | .. |
---|
44 | 45 | #define RKVENC_MAX_DCHS_ID 4 |
---|
45 | 46 | #define RKVENC_MAX_SLICE_FIFO_LEN 256 |
---|
46 | 47 | #define RKVENC_SCLR_DONE_STA BIT(2) |
---|
| 48 | +#define RKVENC_WDG 0x38 |
---|
| 49 | +#define TIMEOUT_MS 100 |
---|
47 | 50 | |
---|
48 | 51 | #define to_rkvenc_info(info) \ |
---|
49 | 52 | container_of(info, struct rkvenc_hw_info, hw) |
---|
.. | .. |
---|
127 | 130 | #define INT_STA_WBUS_ERR_STA BIT(6) |
---|
128 | 131 | #define INT_STA_RBUS_ERR_STA BIT(7) |
---|
129 | 132 | #define INT_STA_WDG_STA BIT(8) |
---|
| 133 | + |
---|
| 134 | +#define INT_STA_ERROR (INT_STA_BRSP_OTSD_STA | \ |
---|
| 135 | + INT_STA_WBUS_ERR_STA | \ |
---|
| 136 | + INT_STA_RBUS_ERR_STA | \ |
---|
| 137 | + INT_STA_WDG_STA) |
---|
130 | 138 | |
---|
131 | 139 | #define DCHS_REG_OFFSET (0x304) |
---|
132 | 140 | #define DCHS_CLASS_OFFSET (33) |
---|
.. | .. |
---|
294 | 302 | #ifdef CONFIG_PM_DEVFREQ |
---|
295 | 303 | struct rockchip_opp_info opp_info; |
---|
296 | 304 | struct monitor_dev_info *mdev_info; |
---|
| 305 | + struct opp_table *opp_table; |
---|
297 | 306 | #endif |
---|
298 | 307 | }; |
---|
299 | 308 | |
---|
.. | .. |
---|
1194 | 1203 | struct rkvenc_task *task = to_rkvenc_task(mpp_task); |
---|
1195 | 1204 | struct rkvenc_hw_info *hw = enc->hw_info; |
---|
1196 | 1205 | u32 timing_en = mpp->srv->timing_en; |
---|
| 1206 | + u32 timeout_thd; |
---|
1197 | 1207 | |
---|
1198 | 1208 | mpp_debug_enter(); |
---|
1199 | 1209 | |
---|
.. | .. |
---|
1242 | 1252 | /* init current task */ |
---|
1243 | 1253 | mpp->cur_task = mpp_task; |
---|
1244 | 1254 | |
---|
| 1255 | + /* |
---|
| 1256 | + * reconfig timeout threshold. |
---|
| 1257 | + * bit0-bit23,x1024 core clk cycles |
---|
| 1258 | + */ |
---|
| 1259 | + timeout_thd = mpp_read(mpp, RKVENC_WDG) & 0xff000000; |
---|
| 1260 | + timeout_thd |= TIMEOUT_MS * clk_get_rate(enc->core_clk_info.clk) / 1024000; |
---|
| 1261 | + mpp_write(mpp, RKVENC_WDG, timeout_thd); |
---|
| 1262 | + |
---|
1245 | 1263 | mpp_task_run_begin(mpp_task, timing_en, MPP_WORK_TIMEOUT_DELAY); |
---|
1246 | 1264 | |
---|
1247 | 1265 | /* Flush the register before the start the device */ |
---|
1248 | 1266 | wmb(); |
---|
1249 | | - |
---|
1250 | 1267 | mpp_write(mpp, enc->hw_info->enc_start_base, start_val); |
---|
1251 | 1268 | |
---|
1252 | 1269 | mpp_task_run_end(mpp_task, timing_en); |
---|
.. | .. |
---|
1256 | 1273 | return 0; |
---|
1257 | 1274 | } |
---|
1258 | 1275 | |
---|
1259 | | -static void rkvenc2_read_slice_len(struct mpp_dev *mpp, struct rkvenc_task *task) |
---|
| 1276 | +static void rkvenc2_read_slice_len(struct mpp_dev *mpp, struct rkvenc_task *task, |
---|
| 1277 | + u32 last) |
---|
1260 | 1278 | { |
---|
1261 | | - u32 last = mpp_read_relaxed(mpp, 0x002c) & INT_STA_ENC_DONE_STA; |
---|
1262 | 1279 | u32 sli_num = mpp_read_relaxed(mpp, RKVENC2_REG_SLICE_NUM_BASE); |
---|
1263 | 1280 | union rkvenc2_slice_len_info slice_info; |
---|
1264 | 1281 | u32 task_id = task->mpp_task.task_id; |
---|
.. | .. |
---|
1298 | 1315 | struct rkvenc_hw_info *hw = enc->hw_info; |
---|
1299 | 1316 | struct mpp_task *mpp_task = NULL; |
---|
1300 | 1317 | struct rkvenc_task *task = NULL; |
---|
1301 | | - u32 int_clear = 1; |
---|
1302 | | - u32 irq_mask = 0; |
---|
| 1318 | + u32 irq_status; |
---|
1303 | 1319 | int ret = IRQ_NONE; |
---|
1304 | 1320 | |
---|
1305 | 1321 | mpp_debug_enter(); |
---|
1306 | 1322 | |
---|
1307 | | - mpp->irq_status = mpp_read(mpp, hw->int_sta_base); |
---|
1308 | | - if (!mpp->irq_status) |
---|
| 1323 | + irq_status = mpp_read(mpp, hw->int_sta_base); |
---|
| 1324 | + |
---|
| 1325 | + mpp_debug(DEBUG_IRQ_STATUS, "%s irq_status: %08x\n", |
---|
| 1326 | + dev_name(mpp->dev), irq_status); |
---|
| 1327 | + |
---|
| 1328 | + if (!irq_status) |
---|
1309 | 1329 | return ret; |
---|
| 1330 | + |
---|
| 1331 | + /* clear int first */ |
---|
| 1332 | + mpp_write(mpp, hw->int_clr_base, irq_status); |
---|
| 1333 | + |
---|
| 1334 | + /* |
---|
| 1335 | + * prevent watch dog irq storm. |
---|
| 1336 | + * The encoder did not stop working when watchdog interrupt is triggered, |
---|
| 1337 | + * it still check timeout and trigger watch dog irq. |
---|
| 1338 | + */ |
---|
| 1339 | + if (irq_status & INT_STA_WDG_STA) |
---|
| 1340 | + mpp_write(mpp, hw->int_mask_base, INT_STA_WDG_STA); |
---|
1310 | 1341 | |
---|
1311 | 1342 | if (mpp->cur_task) { |
---|
1312 | 1343 | mpp_task = mpp->cur_task; |
---|
1313 | 1344 | task = to_rkvenc_task(mpp_task); |
---|
1314 | 1345 | } |
---|
1315 | 1346 | |
---|
1316 | | - if (mpp->irq_status & INT_STA_ENC_DONE_STA) { |
---|
1317 | | - if (task) { |
---|
1318 | | - if (task->task_split) |
---|
1319 | | - rkvenc2_read_slice_len(mpp, task); |
---|
| 1347 | + /* 1. read slice number and slice length */ |
---|
| 1348 | + if (task && task->task_split && |
---|
| 1349 | + (irq_status & (INT_STA_SLC_DONE_STA | INT_STA_ENC_DONE_STA))) { |
---|
| 1350 | + mpp_time_part_diff(mpp_task); |
---|
| 1351 | + rkvenc2_read_slice_len(mpp, task, irq_status & INT_STA_ENC_DONE_STA); |
---|
| 1352 | + wake_up(&mpp_task->wait); |
---|
| 1353 | + } |
---|
1320 | 1354 | |
---|
1321 | | - wake_up(&mpp_task->wait); |
---|
1322 | | - } |
---|
| 1355 | + /* 2. process slice irq */ |
---|
| 1356 | + if (irq_status & INT_STA_SLC_DONE_STA) |
---|
| 1357 | + ret = IRQ_HANDLED; |
---|
1323 | 1358 | |
---|
1324 | | - irq_mask = INT_STA_ENC_DONE_STA; |
---|
1325 | | - ret = IRQ_WAKE_THREAD; |
---|
1326 | | - if (enc->bs_overflow) { |
---|
1327 | | - mpp->irq_status |= INT_STA_BSF_OFLW_STA; |
---|
1328 | | - enc->bs_overflow = 0; |
---|
1329 | | - } |
---|
1330 | | - } else if (mpp->irq_status & INT_STA_SLC_DONE_STA) { |
---|
1331 | | - if (task && task->task_split) { |
---|
1332 | | - mpp_time_part_diff(mpp_task); |
---|
1333 | | - |
---|
1334 | | - rkvenc2_read_slice_len(mpp, task); |
---|
1335 | | - wake_up(&mpp_task->wait); |
---|
1336 | | - } |
---|
1337 | | - |
---|
1338 | | - irq_mask = INT_STA_ENC_DONE_STA; |
---|
1339 | | - int_clear = 0; |
---|
1340 | | - } else if (mpp->irq_status & INT_STA_BSF_OFLW_STA) { |
---|
| 1359 | + /* 3. process bitstream overflow */ |
---|
| 1360 | + if (irq_status & INT_STA_BSF_OFLW_STA) { |
---|
1341 | 1361 | u32 bs_rd = mpp_read(mpp, RKVENC2_REG_ADR_BSBR); |
---|
1342 | 1362 | u32 bs_wr = mpp_read(mpp, RKVENC2_REG_ST_BSB); |
---|
1343 | 1363 | u32 bs_top = mpp_read(mpp, RKVENC2_REG_ADR_BSBT); |
---|
.. | .. |
---|
1349 | 1369 | bs_wr += 128; |
---|
1350 | 1370 | if (bs_wr >= bs_top) |
---|
1351 | 1371 | bs_wr = bs_bot; |
---|
1352 | | - /* clear int first */ |
---|
1353 | | - mpp_write(mpp, hw->int_clr_base, mpp->irq_status); |
---|
| 1372 | + |
---|
1354 | 1373 | /* update write addr for enc continue */ |
---|
1355 | 1374 | mpp_write(mpp, RKVENC2_REG_ADR_BSBS, bs_wr); |
---|
1356 | 1375 | enc->bs_overflow = 1; |
---|
1357 | | - irq_mask = 0; |
---|
1358 | | - int_clear = 0; |
---|
1359 | | - ret = IRQ_HANDLED; |
---|
1360 | | - } else { |
---|
1361 | | - dev_err(mpp->dev, "found error status %08x\n", mpp->irq_status); |
---|
1362 | 1376 | |
---|
1363 | | - irq_mask = mpp->irq_status; |
---|
| 1377 | + ret = IRQ_HANDLED; |
---|
| 1378 | + } |
---|
| 1379 | + |
---|
| 1380 | + /* 4. process frame irq */ |
---|
| 1381 | + if (irq_status & INT_STA_ENC_DONE_STA) { |
---|
| 1382 | + mpp->irq_status = irq_status; |
---|
| 1383 | + |
---|
| 1384 | + if (enc->bs_overflow) { |
---|
| 1385 | + mpp->irq_status |= INT_STA_BSF_OFLW_STA; |
---|
| 1386 | + enc->bs_overflow = 0; |
---|
| 1387 | + } |
---|
| 1388 | + |
---|
1364 | 1389 | ret = IRQ_WAKE_THREAD; |
---|
1365 | 1390 | } |
---|
1366 | 1391 | |
---|
1367 | | - if (irq_mask) |
---|
1368 | | - mpp_write(mpp, hw->int_mask_base, irq_mask); |
---|
| 1392 | + /* 5. process error irq */ |
---|
| 1393 | + if (irq_status & INT_STA_ERROR) { |
---|
| 1394 | + mpp->irq_status = irq_status; |
---|
1369 | 1395 | |
---|
1370 | | - if (int_clear) { |
---|
1371 | | - mpp_write(mpp, hw->int_clr_base, mpp->irq_status); |
---|
1372 | | - udelay(5); |
---|
1373 | | - mpp_write(mpp, hw->int_sta_base, 0); |
---|
| 1396 | + dev_err(mpp->dev, "found error status %08x\n", irq_status); |
---|
| 1397 | + |
---|
| 1398 | + ret = IRQ_WAKE_THREAD; |
---|
1374 | 1399 | } |
---|
1375 | 1400 | |
---|
1376 | 1401 | mpp_debug_leave(); |
---|
1377 | 1402 | |
---|
1378 | 1403 | return ret; |
---|
| 1404 | +} |
---|
| 1405 | + |
---|
| 1406 | +static int vepu540c_irq(struct mpp_dev *mpp) |
---|
| 1407 | +{ |
---|
| 1408 | + return rkvenc_irq(mpp); |
---|
1379 | 1409 | } |
---|
1380 | 1410 | |
---|
1381 | 1411 | static int rkvenc_isr(struct mpp_dev *mpp) |
---|
.. | .. |
---|
1405 | 1435 | task->irq_status = mpp->irq_status; |
---|
1406 | 1436 | |
---|
1407 | 1437 | rkvenc2_update_dchs(enc, task); |
---|
1408 | | - |
---|
1409 | | - mpp_debug(DEBUG_IRQ_STATUS, "%s irq_status: %08x\n", |
---|
1410 | | - dev_name(mpp->dev), task->irq_status); |
---|
1411 | 1438 | |
---|
1412 | 1439 | if (task->irq_status & enc->hw_info->err_mask) { |
---|
1413 | 1440 | atomic_inc(&mpp->reset_request); |
---|
.. | .. |
---|
1458 | 1485 | if (task->bs_buf) { |
---|
1459 | 1486 | u32 bs_size = mpp_read(mpp, 0x4064); |
---|
1460 | 1487 | |
---|
1461 | | - mpp_dma_buf_sync(task->bs_buf, 0, bs_size / 8 + task->offset_bs, |
---|
| 1488 | + mpp_dma_buf_sync(task->bs_buf, 0, bs_size + task->offset_bs, |
---|
1462 | 1489 | DMA_FROM_DEVICE, true); |
---|
1463 | 1490 | } |
---|
1464 | 1491 | |
---|
.. | .. |
---|
1785 | 1812 | if (IS_ERR(reg_table)) |
---|
1786 | 1813 | return PTR_ERR(reg_table); |
---|
1787 | 1814 | } |
---|
| 1815 | + enc->opp_table = reg_table; |
---|
1788 | 1816 | |
---|
1789 | 1817 | clk_table = dev_pm_opp_set_clkname(dev, "clk_core"); |
---|
1790 | | - if (IS_ERR(clk_table)) |
---|
1791 | | - return PTR_ERR(clk_table); |
---|
| 1818 | + if (IS_ERR(clk_table)) { |
---|
| 1819 | + ret = PTR_ERR(clk_table); |
---|
| 1820 | + goto put_opp_reg; |
---|
| 1821 | + } |
---|
1792 | 1822 | |
---|
1793 | 1823 | rockchip_get_opp_data(rockchip_rkvenc_of_match, &enc->opp_info); |
---|
1794 | 1824 | ret = rockchip_init_opp_table(dev, &enc->opp_info, "leakage", "venc"); |
---|
1795 | 1825 | if (ret) { |
---|
1796 | 1826 | dev_err(dev, "failed to init_opp_table\n"); |
---|
1797 | | - return ret; |
---|
| 1827 | + goto put_opp_clk; |
---|
1798 | 1828 | } |
---|
1799 | 1829 | |
---|
1800 | 1830 | enc->mdev_info = rockchip_system_monitor_register(dev, &venc_mdevp); |
---|
.. | .. |
---|
1803 | 1833 | enc->mdev_info = NULL; |
---|
1804 | 1834 | } |
---|
1805 | 1835 | |
---|
| 1836 | + return 0; |
---|
| 1837 | + |
---|
| 1838 | +put_opp_clk: |
---|
| 1839 | + dev_pm_opp_put_clkname(enc->opp_table); |
---|
| 1840 | +put_opp_reg: |
---|
| 1841 | + dev_pm_opp_put_regulators(enc->opp_table); |
---|
| 1842 | + enc->opp_table = NULL; |
---|
| 1843 | + |
---|
1806 | 1844 | return ret; |
---|
1807 | 1845 | } |
---|
1808 | 1846 | |
---|
.. | .. |
---|
1810 | 1848 | { |
---|
1811 | 1849 | struct rkvenc_dev *enc = to_rkvenc_dev(mpp); |
---|
1812 | 1850 | |
---|
1813 | | - if (enc->mdev_info) |
---|
| 1851 | + if (enc->mdev_info) { |
---|
1814 | 1852 | rockchip_system_monitor_unregister(enc->mdev_info); |
---|
| 1853 | + enc->mdev_info = NULL; |
---|
| 1854 | + } |
---|
| 1855 | + if (enc->opp_table) { |
---|
| 1856 | + rockchip_uninit_opp_table(mpp->dev, &enc->opp_info); |
---|
| 1857 | + dev_pm_opp_put_clkname(enc->opp_table); |
---|
| 1858 | + dev_pm_opp_put_regulators(enc->opp_table); |
---|
| 1859 | + enc->opp_table = NULL; |
---|
| 1860 | + } |
---|
1815 | 1861 | |
---|
1816 | 1862 | return 0; |
---|
1817 | 1863 | } |
---|
.. | .. |
---|
1880 | 1926 | |
---|
1881 | 1927 | /* safe reset */ |
---|
1882 | 1928 | mpp_write(mpp, hw->int_mask_base, 0x3FF); |
---|
1883 | | - mpp_write(mpp, hw->enc_clr_base, 0x1); |
---|
| 1929 | + mpp_write(mpp, hw->enc_clr_base, 0x3); |
---|
1884 | 1930 | ret = readl_relaxed_poll_timeout(mpp->reg_base + hw->int_sta_base, |
---|
1885 | 1931 | rst_status, |
---|
1886 | 1932 | rst_status & RKVENC_SCLR_DONE_STA, |
---|
.. | .. |
---|
2169 | 2215 | .dump_session = rkvenc_dump_session, |
---|
2170 | 2216 | }; |
---|
2171 | 2217 | |
---|
| 2218 | +static struct mpp_dev_ops vepu540c_dev_ops_v2 = { |
---|
| 2219 | + .wait_result = rkvenc2_wait_result, |
---|
| 2220 | + .alloc_task = rkvenc_alloc_task, |
---|
| 2221 | + .run = rkvenc_run, |
---|
| 2222 | + .irq = vepu540c_irq, |
---|
| 2223 | + .isr = rkvenc_isr, |
---|
| 2224 | + .finish = rkvenc_finish, |
---|
| 2225 | + .result = rkvenc_result, |
---|
| 2226 | + .free_task = rkvenc_free_task, |
---|
| 2227 | + .ioctl = rkvenc_control, |
---|
| 2228 | + .init_session = rkvenc_init_session, |
---|
| 2229 | + .free_session = rkvenc_free_session, |
---|
| 2230 | + .dump_session = rkvenc_dump_session, |
---|
| 2231 | +}; |
---|
2172 | 2232 | |
---|
2173 | 2233 | static const struct mpp_dev_var rkvenc_v2_data = { |
---|
2174 | 2234 | .device_type = MPP_DEVICE_RKVENC, |
---|
.. | .. |
---|
2183 | 2243 | .hw_info = &rkvenc_540c_hw_info.hw, |
---|
2184 | 2244 | .trans_info = trans_rkvenc_540c, |
---|
2185 | 2245 | .hw_ops = &rkvenc_hw_ops, |
---|
2186 | | - .dev_ops = &rkvenc_dev_ops_v2, |
---|
| 2246 | + .dev_ops = &vepu540c_dev_ops_v2, |
---|
2187 | 2247 | }; |
---|
2188 | 2248 | |
---|
2189 | 2249 | static const struct mpp_dev_var rkvenc_ccu_data = { |
---|
.. | .. |
---|
2404 | 2464 | { |
---|
2405 | 2465 | struct mpp_dev *mpp = (struct mpp_dev *)arg; |
---|
2406 | 2466 | struct rkvenc_dev *enc = to_rkvenc_dev(mpp); |
---|
2407 | | - struct mpp_task *mpp_task = mpp->cur_task; |
---|
| 2467 | + struct mpp_task *mpp_task; |
---|
| 2468 | + struct rkvenc_ccu *ccu = enc->ccu; |
---|
2408 | 2469 | |
---|
| 2470 | + if (ccu) { |
---|
| 2471 | + struct rkvenc_dev *core = NULL, *n; |
---|
| 2472 | + |
---|
| 2473 | + list_for_each_entry_safe(core, n, &ccu->core_list, core_link) { |
---|
| 2474 | + if (core->mpp.iommu_info && |
---|
| 2475 | + (&core->mpp.iommu_info->pdev->dev == iommu_dev)) { |
---|
| 2476 | + mpp = &core->mpp; |
---|
| 2477 | + break; |
---|
| 2478 | + } |
---|
| 2479 | + } |
---|
| 2480 | + } |
---|
| 2481 | + mpp_task = mpp->cur_task; |
---|
2409 | 2482 | dev_info(mpp->dev, "core %d page fault found dchs %08x\n", |
---|
2410 | 2483 | mpp->core_id, mpp_read_relaxed(&enc->mpp, DCHS_REG_OFFSET)); |
---|
2411 | 2484 | |
---|
2412 | 2485 | if (mpp_task) |
---|
2413 | 2486 | mpp_task_dump_mem_region(mpp, mpp_task); |
---|
| 2487 | + |
---|
| 2488 | + /* |
---|
| 2489 | + * Mask iommu irq, in order for iommu not repeatedly trigger pagefault. |
---|
| 2490 | + * Until the pagefault task finish by hw timeout. |
---|
| 2491 | + */ |
---|
| 2492 | + rockchip_iommu_mask_irq(mpp->dev); |
---|
2414 | 2493 | |
---|
2415 | 2494 | return 0; |
---|
2416 | 2495 | } |
---|
.. | .. |
---|
2455 | 2534 | ret = devm_request_threaded_irq(dev, mpp->irq, |
---|
2456 | 2535 | mpp_dev_irq, |
---|
2457 | 2536 | mpp_dev_isr_sched, |
---|
2458 | | - IRQF_SHARED, |
---|
| 2537 | + IRQF_ONESHOT, |
---|
2459 | 2538 | dev_name(dev), mpp); |
---|
2460 | 2539 | if (ret) { |
---|
2461 | 2540 | dev_err(dev, "register interrupter runtime failed\n"); |
---|