linux/drivers/media/platform/sti/hva/hva-hw.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) STMicroelectronics SA 2015
   3 * Authors: Yannick Fertre <yannick.fertre@st.com>
   4 *          Hugues Fruchet <hugues.fruchet@st.com>
   5 * License terms:  GNU General Public License (GPL), version 2
   6 */
   7
   8#include <linux/clk.h>
   9#include <linux/interrupt.h>
  10#include <linux/platform_device.h>
  11#include <linux/pm_runtime.h>
  12
  13#include "hva.h"
  14#include "hva-hw.h"
  15
  16/* HVA register offsets */
  17#define HVA_HIF_REG_RST                 0x0100U
  18#define HVA_HIF_REG_RST_ACK             0x0104U
  19#define HVA_HIF_REG_MIF_CFG             0x0108U
  20#define HVA_HIF_REG_HEC_MIF_CFG         0x010CU
  21#define HVA_HIF_REG_CFL                 0x0110U
  22#define HVA_HIF_FIFO_CMD                0x0114U
  23#define HVA_HIF_FIFO_STS                0x0118U
  24#define HVA_HIF_REG_SFL                 0x011CU
  25#define HVA_HIF_REG_IT_ACK              0x0120U
  26#define HVA_HIF_REG_ERR_IT_ACK          0x0124U
  27#define HVA_HIF_REG_LMI_ERR             0x0128U
  28#define HVA_HIF_REG_EMI_ERR             0x012CU
  29#define HVA_HIF_REG_HEC_MIF_ERR         0x0130U
  30#define HVA_HIF_REG_HEC_STS             0x0134U
  31#define HVA_HIF_REG_HVC_STS             0x0138U
  32#define HVA_HIF_REG_HJE_STS             0x013CU
  33#define HVA_HIF_REG_CNT                 0x0140U
  34#define HVA_HIF_REG_HEC_CHKSYN_DIS      0x0144U
  35#define HVA_HIF_REG_CLK_GATING          0x0148U
  36#define HVA_HIF_REG_VERSION             0x014CU
  37#define HVA_HIF_REG_BSM                 0x0150U
  38
  39/* define value for version id register (HVA_HIF_REG_VERSION) */
  40#define VERSION_ID_MASK 0x0000FFFF
  41
  42/* define values for BSM register (HVA_HIF_REG_BSM) */
  43#define BSM_CFG_VAL1    0x0003F000
  44#define BSM_CFG_VAL2    0x003F0000
  45
  46/* define values for memory interface register (HVA_HIF_REG_MIF_CFG) */
  47#define MIF_CFG_VAL1    0x04460446
  48#define MIF_CFG_VAL2    0x04460806
  49#define MIF_CFG_VAL3    0x00000000
  50
  51/* define value for HEC memory interface register (HVA_HIF_REG_MIF_CFG) */
  52#define HEC_MIF_CFG_VAL 0x000000C4
  53
  54/*  Bits definition for clock gating register (HVA_HIF_REG_CLK_GATING) */
  55#define CLK_GATING_HVC  BIT(0)
  56#define CLK_GATING_HEC  BIT(1)
  57#define CLK_GATING_HJE  BIT(2)
  58
  59/* fix hva clock rate */
  60#define CLK_RATE                300000000
  61
  62/* fix delay for pmruntime */
  63#define AUTOSUSPEND_DELAY_MS    3
  64
  65/*
  66 * hw encode error values
  67 * NO_ERROR: Success, Task OK
  68 * H264_BITSTREAM_OVERSIZE: VECH264 Bitstream size > bitstream buffer
  69 * H264_FRAME_SKIPPED: VECH264 Frame skipped (refers to CPB Buffer Size)
  70 * H264_SLICE_LIMIT_SIZE: VECH264 MB > slice limit size
  71 * H264_MAX_SLICE_NUMBER: VECH264 max slice number reached
  72 * H264_SLICE_READY: VECH264 Slice ready
  73 * TASK_LIST_FULL: HVA/FPC task list full
  74                   (discard latest transform command)
  75 * UNKNOWN_COMMAND: Transform command not known by HVA/FPC
  76 * WRONG_CODEC_OR_RESOLUTION: Wrong Codec or Resolution Selection
  77 * NO_INT_COMPLETION: Time-out on interrupt completion
  78 * LMI_ERR: Local Memory Interface Error
  79 * EMI_ERR: External Memory Interface Error
  80 * HECMI_ERR: HEC Memory Interface Error
  81 */
  82enum hva_hw_error {
  83        NO_ERROR = 0x0,
  84        H264_BITSTREAM_OVERSIZE = 0x2,
  85        H264_FRAME_SKIPPED = 0x4,
  86        H264_SLICE_LIMIT_SIZE = 0x5,
  87        H264_MAX_SLICE_NUMBER = 0x7,
  88        H264_SLICE_READY = 0x8,
  89        TASK_LIST_FULL = 0xF0,
  90        UNKNOWN_COMMAND = 0xF1,
  91        WRONG_CODEC_OR_RESOLUTION = 0xF4,
  92        NO_INT_COMPLETION = 0x100,
  93        LMI_ERR = 0x101,
  94        EMI_ERR = 0x102,
  95        HECMI_ERR = 0x103,
  96};
  97
  98static irqreturn_t hva_hw_its_interrupt(int irq, void *data)
  99{
 100        struct hva_dev *hva = data;
 101
 102        /* read status registers */
 103        hva->sts_reg = readl_relaxed(hva->regs + HVA_HIF_FIFO_STS);
 104        hva->sfl_reg = readl_relaxed(hva->regs + HVA_HIF_REG_SFL);
 105
 106        /* acknowledge interruption */
 107        writel_relaxed(0x1, hva->regs + HVA_HIF_REG_IT_ACK);
 108
 109        return IRQ_WAKE_THREAD;
 110}
 111
 112static irqreturn_t hva_hw_its_irq_thread(int irq, void *arg)
 113{
 114        struct hva_dev *hva = arg;
 115        struct device *dev = hva_to_dev(hva);
 116        u32 status = hva->sts_reg & 0xFF;
 117        u8 ctx_id = 0;
 118        struct hva_ctx *ctx = NULL;
 119
 120        dev_dbg(dev, "%s     %s: status: 0x%02x fifo level: 0x%02x\n",
 121                HVA_PREFIX, __func__, hva->sts_reg & 0xFF, hva->sfl_reg & 0xF);
 122
 123        /*
 124         * status: task_id[31:16] client_id[15:8] status[7:0]
 125         * the context identifier is retrieved from the client identifier
 126         */
 127        ctx_id = (hva->sts_reg & 0xFF00) >> 8;
 128        if (ctx_id >= HVA_MAX_INSTANCES) {
 129                dev_err(dev, "%s     %s: bad context identifier: %d\n",
 130                        ctx->name, __func__, ctx_id);
 131                ctx->hw_err = true;
 132                goto out;
 133        }
 134
 135        ctx = hva->instances[ctx_id];
 136        if (!ctx)
 137                goto out;
 138
 139        switch (status) {
 140        case NO_ERROR:
 141                dev_dbg(dev, "%s     %s: no error\n",
 142                        ctx->name, __func__);
 143                ctx->hw_err = false;
 144                break;
 145        case H264_SLICE_READY:
 146                dev_dbg(dev, "%s     %s: h264 slice ready\n",
 147                        ctx->name, __func__);
 148                ctx->hw_err = false;
 149                break;
 150        case H264_FRAME_SKIPPED:
 151                dev_dbg(dev, "%s     %s: h264 frame skipped\n",
 152                        ctx->name, __func__);
 153                ctx->hw_err = false;
 154                break;
 155        case H264_BITSTREAM_OVERSIZE:
 156                dev_err(dev, "%s     %s:h264 bitstream oversize\n",
 157                        ctx->name, __func__);
 158                ctx->hw_err = true;
 159                break;
 160        case H264_SLICE_LIMIT_SIZE:
 161                dev_err(dev, "%s     %s: h264 slice limit size is reached\n",
 162                        ctx->name, __func__);
 163                ctx->hw_err = true;
 164                break;
 165        case H264_MAX_SLICE_NUMBER:
 166                dev_err(dev, "%s     %s: h264 max slice number is reached\n",
 167                        ctx->name, __func__);
 168                ctx->hw_err = true;
 169                break;
 170        case TASK_LIST_FULL:
 171                dev_err(dev, "%s     %s:task list full\n",
 172                        ctx->name, __func__);
 173                ctx->hw_err = true;
 174                break;
 175        case UNKNOWN_COMMAND:
 176                dev_err(dev, "%s     %s: command not known\n",
 177                        ctx->name, __func__);
 178                ctx->hw_err = true;
 179                break;
 180        case WRONG_CODEC_OR_RESOLUTION:
 181                dev_err(dev, "%s     %s: wrong codec or resolution\n",
 182                        ctx->name, __func__);
 183                ctx->hw_err = true;
 184                break;
 185        default:
 186                dev_err(dev, "%s     %s: status not recognized\n",
 187                        ctx->name, __func__);
 188                ctx->hw_err = true;
 189                break;
 190        }
 191out:
 192        complete(&hva->interrupt);
 193
 194        return IRQ_HANDLED;
 195}
 196
 197static irqreturn_t hva_hw_err_interrupt(int irq, void *data)
 198{
 199        struct hva_dev *hva = data;
 200
 201        /* read status registers */
 202        hva->sts_reg = readl_relaxed(hva->regs + HVA_HIF_FIFO_STS);
 203        hva->sfl_reg = readl_relaxed(hva->regs + HVA_HIF_REG_SFL);
 204
 205        /* read error registers */
 206        hva->lmi_err_reg = readl_relaxed(hva->regs + HVA_HIF_REG_LMI_ERR);
 207        hva->emi_err_reg = readl_relaxed(hva->regs + HVA_HIF_REG_EMI_ERR);
 208        hva->hec_mif_err_reg = readl_relaxed(hva->regs +
 209                                             HVA_HIF_REG_HEC_MIF_ERR);
 210
 211        /* acknowledge interruption */
 212        writel_relaxed(0x1, hva->regs + HVA_HIF_REG_IT_ACK);
 213
 214        return IRQ_WAKE_THREAD;
 215}
 216
 217static irqreturn_t hva_hw_err_irq_thread(int irq, void *arg)
 218{
 219        struct hva_dev *hva = arg;
 220        struct device *dev = hva_to_dev(hva);
 221        u8 ctx_id = 0;
 222        struct hva_ctx *ctx;
 223
 224        dev_dbg(dev, "%s     status: 0x%02x fifo level: 0x%02x\n",
 225                HVA_PREFIX, hva->sts_reg & 0xFF, hva->sfl_reg & 0xF);
 226
 227        /*
 228         * status: task_id[31:16] client_id[15:8] status[7:0]
 229         * the context identifier is retrieved from the client identifier
 230         */
 231        ctx_id = (hva->sts_reg & 0xFF00) >> 8;
 232        if (ctx_id >= HVA_MAX_INSTANCES) {
 233                dev_err(dev, "%s     bad context identifier: %d\n", HVA_PREFIX,
 234                        ctx_id);
 235                goto out;
 236        }
 237
 238        ctx = hva->instances[ctx_id];
 239        if (!ctx)
 240                goto out;
 241
 242        if (hva->lmi_err_reg) {
 243                dev_err(dev, "%s     local memory interface error: 0x%08x\n",
 244                        ctx->name, hva->lmi_err_reg);
 245                ctx->hw_err = true;
 246        }
 247
 248        if (hva->lmi_err_reg) {
 249                dev_err(dev, "%s     external memory interface error: 0x%08x\n",
 250                        ctx->name, hva->emi_err_reg);
 251                ctx->hw_err = true;
 252        }
 253
 254        if (hva->hec_mif_err_reg) {
 255                dev_err(dev, "%s     hec memory interface error: 0x%08x\n",
 256                        ctx->name, hva->hec_mif_err_reg);
 257                ctx->hw_err = true;
 258        }
 259out:
 260        complete(&hva->interrupt);
 261
 262        return IRQ_HANDLED;
 263}
 264
 265static unsigned long int hva_hw_get_ip_version(struct hva_dev *hva)
 266{
 267        struct device *dev = hva_to_dev(hva);
 268        unsigned long int version;
 269
 270        if (pm_runtime_get_sync(dev) < 0) {
 271                dev_err(dev, "%s     failed to get pm_runtime\n", HVA_PREFIX);
 272                mutex_unlock(&hva->protect_mutex);
 273                return -EFAULT;
 274        }
 275
 276        version = readl_relaxed(hva->regs + HVA_HIF_REG_VERSION) &
 277                                VERSION_ID_MASK;
 278
 279        pm_runtime_put_autosuspend(dev);
 280
 281        switch (version) {
 282        case HVA_VERSION_V400:
 283                dev_dbg(dev, "%s     IP hardware version 0x%lx\n",
 284                        HVA_PREFIX, version);
 285                break;
 286        default:
 287                dev_err(dev, "%s     unknown IP hardware version 0x%lx\n",
 288                        HVA_PREFIX, version);
 289                version = HVA_VERSION_UNKNOWN;
 290                break;
 291        }
 292
 293        return version;
 294}
 295
 296int hva_hw_probe(struct platform_device *pdev, struct hva_dev *hva)
 297{
 298        struct device *dev = &pdev->dev;
 299        struct resource *regs;
 300        struct resource *esram;
 301        int ret;
 302
 303        WARN_ON(!hva);
 304
 305        /* get memory for registers */
 306        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 307        hva->regs = devm_ioremap_resource(dev, regs);
 308        if (IS_ERR_OR_NULL(hva->regs)) {
 309                dev_err(dev, "%s     failed to get regs\n", HVA_PREFIX);
 310                return PTR_ERR(hva->regs);
 311        }
 312
 313        /* get memory for esram */
 314        esram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 315        if (IS_ERR_OR_NULL(esram)) {
 316                dev_err(dev, "%s     failed to get esram\n", HVA_PREFIX);
 317                return PTR_ERR(esram);
 318        }
 319        hva->esram_addr = esram->start;
 320        hva->esram_size = resource_size(esram);
 321
 322        dev_info(dev, "%s     esram reserved for address: 0x%x size:%d\n",
 323                 HVA_PREFIX, hva->esram_addr, hva->esram_size);
 324
 325        /* get clock resource */
 326        hva->clk = devm_clk_get(dev, "clk_hva");
 327        if (IS_ERR(hva->clk)) {
 328                dev_err(dev, "%s     failed to get clock\n", HVA_PREFIX);
 329                return PTR_ERR(hva->clk);
 330        }
 331
 332        ret = clk_prepare(hva->clk);
 333        if (ret < 0) {
 334                dev_err(dev, "%s     failed to prepare clock\n", HVA_PREFIX);
 335                hva->clk = ERR_PTR(-EINVAL);
 336                return ret;
 337        }
 338
 339        /* get status interruption resource */
 340        ret  = platform_get_irq(pdev, 0);
 341        if (ret < 0) {
 342                dev_err(dev, "%s     failed to get status IRQ\n", HVA_PREFIX);
 343                goto err_clk;
 344        }
 345        hva->irq_its = ret;
 346
 347        ret = devm_request_threaded_irq(dev, hva->irq_its, hva_hw_its_interrupt,
 348                                        hva_hw_its_irq_thread,
 349                                        IRQF_ONESHOT,
 350                                        "hva_its_irq", hva);
 351        if (ret) {
 352                dev_err(dev, "%s     failed to install status IRQ 0x%x\n",
 353                        HVA_PREFIX, hva->irq_its);
 354                goto err_clk;
 355        }
 356        disable_irq(hva->irq_its);
 357
 358        /* get error interruption resource */
 359        ret = platform_get_irq(pdev, 1);
 360        if (ret < 0) {
 361                dev_err(dev, "%s     failed to get error IRQ\n", HVA_PREFIX);
 362                goto err_clk;
 363        }
 364        hva->irq_err = ret;
 365
 366        ret = devm_request_threaded_irq(dev, hva->irq_err, hva_hw_err_interrupt,
 367                                        hva_hw_err_irq_thread,
 368                                        IRQF_ONESHOT,
 369                                        "hva_err_irq", hva);
 370        if (ret) {
 371                dev_err(dev, "%s     failed to install error IRQ 0x%x\n",
 372                        HVA_PREFIX, hva->irq_err);
 373                goto err_clk;
 374        }
 375        disable_irq(hva->irq_err);
 376
 377        /* initialise protection mutex */
 378        mutex_init(&hva->protect_mutex);
 379
 380        /* initialise completion signal */
 381        init_completion(&hva->interrupt);
 382
 383        /* initialise runtime power management */
 384        pm_runtime_set_autosuspend_delay(dev, AUTOSUSPEND_DELAY_MS);
 385        pm_runtime_use_autosuspend(dev);
 386        pm_runtime_set_suspended(dev);
 387        pm_runtime_enable(dev);
 388
 389        ret = pm_runtime_get_sync(dev);
 390        if (ret < 0) {
 391                dev_err(dev, "%s     failed to set PM\n", HVA_PREFIX);
 392                goto err_clk;
 393        }
 394
 395        /* check IP hardware version */
 396        hva->ip_version = hva_hw_get_ip_version(hva);
 397
 398        if (hva->ip_version == HVA_VERSION_UNKNOWN) {
 399                ret = -EINVAL;
 400                goto err_pm;
 401        }
 402
 403        dev_info(dev, "%s     found hva device (version 0x%lx)\n", HVA_PREFIX,
 404                 hva->ip_version);
 405
 406        return 0;
 407
 408err_pm:
 409        pm_runtime_put(dev);
 410err_clk:
 411        if (hva->clk)
 412                clk_unprepare(hva->clk);
 413
 414        return ret;
 415}
 416
 417void hva_hw_remove(struct hva_dev *hva)
 418{
 419        struct device *dev = hva_to_dev(hva);
 420
 421        disable_irq(hva->irq_its);
 422        disable_irq(hva->irq_err);
 423
 424        pm_runtime_put_autosuspend(dev);
 425        pm_runtime_disable(dev);
 426}
 427
 428int hva_hw_runtime_suspend(struct device *dev)
 429{
 430        struct hva_dev *hva = dev_get_drvdata(dev);
 431
 432        clk_disable_unprepare(hva->clk);
 433
 434        return 0;
 435}
 436
 437int hva_hw_runtime_resume(struct device *dev)
 438{
 439        struct hva_dev *hva = dev_get_drvdata(dev);
 440
 441        if (clk_prepare_enable(hva->clk)) {
 442                dev_err(hva->dev, "%s     failed to prepare hva clk\n",
 443                        HVA_PREFIX);
 444                return -EINVAL;
 445        }
 446
 447        if (clk_set_rate(hva->clk, CLK_RATE)) {
 448                dev_err(dev, "%s     failed to set clock frequency\n",
 449                        HVA_PREFIX);
 450                return -EINVAL;
 451        }
 452
 453        return 0;
 454}
 455
 456int hva_hw_execute_task(struct hva_ctx *ctx, enum hva_hw_cmd_type cmd,
 457                        struct hva_buffer *task)
 458{
 459        struct hva_dev *hva = ctx_to_hdev(ctx);
 460        struct device *dev = hva_to_dev(hva);
 461        u8 client_id = ctx->id;
 462        int ret;
 463        u32 reg = 0;
 464
 465        mutex_lock(&hva->protect_mutex);
 466
 467        /* enable irqs */
 468        enable_irq(hva->irq_its);
 469        enable_irq(hva->irq_err);
 470
 471        if (pm_runtime_get_sync(dev) < 0) {
 472                dev_err(dev, "%s     failed to get pm_runtime\n", ctx->name);
 473                ret = -EFAULT;
 474                goto out;
 475        }
 476
 477        reg = readl_relaxed(hva->regs + HVA_HIF_REG_CLK_GATING);
 478        switch (cmd) {
 479        case H264_ENC:
 480                reg |= CLK_GATING_HVC;
 481                break;
 482        default:
 483                dev_dbg(dev, "%s     unknown command 0x%x\n", ctx->name, cmd);
 484                ret = -EFAULT;
 485                goto out;
 486        }
 487        writel_relaxed(reg, hva->regs + HVA_HIF_REG_CLK_GATING);
 488
 489        dev_dbg(dev, "%s     %s: write configuration registers\n", ctx->name,
 490                __func__);
 491
 492        /* byte swap config */
 493        writel_relaxed(BSM_CFG_VAL1, hva->regs + HVA_HIF_REG_BSM);
 494
 495        /* define Max Opcode Size and Max Message Size for LMI and EMI */
 496        writel_relaxed(MIF_CFG_VAL3, hva->regs + HVA_HIF_REG_MIF_CFG);
 497        writel_relaxed(HEC_MIF_CFG_VAL, hva->regs + HVA_HIF_REG_HEC_MIF_CFG);
 498
 499        /*
 500         * command FIFO: task_id[31:16] client_id[15:8] command_type[7:0]
 501         * the context identifier is provided as client identifier to the
 502         * hardware, and is retrieved in the interrupt functions from the
 503         * status register
 504         */
 505        dev_dbg(dev, "%s     %s: send task (cmd: %d, task_desc: %pad)\n",
 506                ctx->name, __func__, cmd + (client_id << 8), &task->paddr);
 507        writel_relaxed(cmd + (client_id << 8), hva->regs + HVA_HIF_FIFO_CMD);
 508        writel_relaxed(task->paddr, hva->regs + HVA_HIF_FIFO_CMD);
 509
 510        if (!wait_for_completion_timeout(&hva->interrupt,
 511                                         msecs_to_jiffies(2000))) {
 512                dev_err(dev, "%s     %s: time out on completion\n", ctx->name,
 513                        __func__);
 514                ret = -EFAULT;
 515                goto out;
 516        }
 517
 518        /* get encoding status */
 519        ret = ctx->hw_err ? -EFAULT : 0;
 520
 521out:
 522        disable_irq(hva->irq_its);
 523        disable_irq(hva->irq_err);
 524
 525        switch (cmd) {
 526        case H264_ENC:
 527                reg &= ~CLK_GATING_HVC;
 528                writel_relaxed(reg, hva->regs + HVA_HIF_REG_CLK_GATING);
 529                break;
 530        default:
 531                dev_dbg(dev, "%s     unknown command 0x%x\n", ctx->name, cmd);
 532        }
 533
 534        pm_runtime_put_autosuspend(dev);
 535        mutex_unlock(&hva->protect_mutex);
 536
 537        return ret;
 538}
 539