linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd_v5.c
   4 *
   5 * Copyright (C) 2011 Samsung Electronics Co., Ltd.
   6 *              http://www.samsung.com/
   7 */
   8
   9#include "regs-mfc.h"
  10#include "s5p_mfc_cmd.h"
  11#include "s5p_mfc_common.h"
  12#include "s5p_mfc_debug.h"
  13#include "s5p_mfc_cmd_v5.h"
  14
  15/* This function is used to send a command to the MFC */
  16static int s5p_mfc_cmd_host2risc_v5(struct s5p_mfc_dev *dev, int cmd,
  17                                struct s5p_mfc_cmd_args *args)
  18{
  19        int cur_cmd;
  20        unsigned long timeout;
  21
  22        timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
  23        /* wait until host to risc command register becomes 'H2R_CMD_EMPTY' */
  24        do {
  25                if (time_after(jiffies, timeout)) {
  26                        mfc_err("Timeout while waiting for hardware\n");
  27                        return -EIO;
  28                }
  29                cur_cmd = mfc_read(dev, S5P_FIMV_HOST2RISC_CMD);
  30        } while (cur_cmd != S5P_FIMV_H2R_CMD_EMPTY);
  31        mfc_write(dev, args->arg[0], S5P_FIMV_HOST2RISC_ARG1);
  32        mfc_write(dev, args->arg[1], S5P_FIMV_HOST2RISC_ARG2);
  33        mfc_write(dev, args->arg[2], S5P_FIMV_HOST2RISC_ARG3);
  34        mfc_write(dev, args->arg[3], S5P_FIMV_HOST2RISC_ARG4);
  35        /* Issue the command */
  36        mfc_write(dev, cmd, S5P_FIMV_HOST2RISC_CMD);
  37        return 0;
  38}
  39
  40/* Initialize the MFC */
  41static int s5p_mfc_sys_init_cmd_v5(struct s5p_mfc_dev *dev)
  42{
  43        struct s5p_mfc_cmd_args h2r_args;
  44
  45        memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
  46        h2r_args.arg[0] = dev->fw_buf.size;
  47        return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SYS_INIT,
  48                        &h2r_args);
  49}
  50
  51/* Suspend the MFC hardware */
  52static int s5p_mfc_sleep_cmd_v5(struct s5p_mfc_dev *dev)
  53{
  54        struct s5p_mfc_cmd_args h2r_args;
  55
  56        memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
  57        return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_SLEEP, &h2r_args);
  58}
  59
  60/* Wake up the MFC hardware */
  61static int s5p_mfc_wakeup_cmd_v5(struct s5p_mfc_dev *dev)
  62{
  63        struct s5p_mfc_cmd_args h2r_args;
  64
  65        memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
  66        return s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_WAKEUP,
  67                        &h2r_args);
  68}
  69
  70
  71static int s5p_mfc_open_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
  72{
  73        struct s5p_mfc_dev *dev = ctx->dev;
  74        struct s5p_mfc_cmd_args h2r_args;
  75        int ret;
  76
  77        /* Preparing decoding - getting instance number */
  78        mfc_debug(2, "Getting instance number (codec: %d)\n", ctx->codec_mode);
  79        dev->curr_ctx = ctx->num;
  80        memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
  81        switch (ctx->codec_mode) {
  82        case S5P_MFC_CODEC_H264_DEC:
  83                h2r_args.arg[0] = S5P_FIMV_CODEC_H264_DEC;
  84                break;
  85        case S5P_MFC_CODEC_VC1_DEC:
  86                h2r_args.arg[0] = S5P_FIMV_CODEC_VC1_DEC;
  87                break;
  88        case S5P_MFC_CODEC_MPEG4_DEC:
  89                h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_DEC;
  90                break;
  91        case S5P_MFC_CODEC_MPEG2_DEC:
  92                h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG2_DEC;
  93                break;
  94        case S5P_MFC_CODEC_H263_DEC:
  95                h2r_args.arg[0] = S5P_FIMV_CODEC_H263_DEC;
  96                break;
  97        case S5P_MFC_CODEC_VC1RCV_DEC:
  98                h2r_args.arg[0] = S5P_FIMV_CODEC_VC1RCV_DEC;
  99                break;
 100        case S5P_MFC_CODEC_H264_ENC:
 101                h2r_args.arg[0] = S5P_FIMV_CODEC_H264_ENC;
 102                break;
 103        case S5P_MFC_CODEC_MPEG4_ENC:
 104                h2r_args.arg[0] = S5P_FIMV_CODEC_MPEG4_ENC;
 105                break;
 106        case S5P_MFC_CODEC_H263_ENC:
 107                h2r_args.arg[0] = S5P_FIMV_CODEC_H263_ENC;
 108                break;
 109        default:
 110                h2r_args.arg[0] = S5P_FIMV_CODEC_NONE;
 111        }
 112        h2r_args.arg[1] = 0; /* no crc & no pixelcache */
 113        h2r_args.arg[2] = ctx->ctx.ofs;
 114        h2r_args.arg[3] = ctx->ctx.size;
 115        ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_OPEN_INSTANCE,
 116                                                                &h2r_args);
 117        if (ret) {
 118                mfc_err("Failed to create a new instance\n");
 119                ctx->state = MFCINST_ERROR;
 120        }
 121        return ret;
 122}
 123
 124static int s5p_mfc_close_inst_cmd_v5(struct s5p_mfc_ctx *ctx)
 125{
 126        struct s5p_mfc_dev *dev = ctx->dev;
 127        struct s5p_mfc_cmd_args h2r_args;
 128        int ret;
 129
 130        if (ctx->state == MFCINST_FREE) {
 131                mfc_err("Instance already returned\n");
 132                ctx->state = MFCINST_ERROR;
 133                return -EINVAL;
 134        }
 135        /* Closing decoding instance  */
 136        mfc_debug(2, "Returning instance number %d\n", ctx->inst_no);
 137        dev->curr_ctx = ctx->num;
 138        memset(&h2r_args, 0, sizeof(struct s5p_mfc_cmd_args));
 139        h2r_args.arg[0] = ctx->inst_no;
 140        ret = s5p_mfc_cmd_host2risc_v5(dev, S5P_FIMV_H2R_CMD_CLOSE_INSTANCE,
 141                                                                &h2r_args);
 142        if (ret) {
 143                mfc_err("Failed to return an instance\n");
 144                ctx->state = MFCINST_ERROR;
 145                return -EINVAL;
 146        }
 147        return 0;
 148}
 149
 150/* Initialize cmd function pointers for MFC v5 */
 151static struct s5p_mfc_hw_cmds s5p_mfc_cmds_v5 = {
 152        .cmd_host2risc = s5p_mfc_cmd_host2risc_v5,
 153        .sys_init_cmd = s5p_mfc_sys_init_cmd_v5,
 154        .sleep_cmd = s5p_mfc_sleep_cmd_v5,
 155        .wakeup_cmd = s5p_mfc_wakeup_cmd_v5,
 156        .open_inst_cmd = s5p_mfc_open_inst_cmd_v5,
 157        .close_inst_cmd = s5p_mfc_close_inst_cmd_v5,
 158};
 159
 160struct s5p_mfc_hw_cmds *s5p_mfc_init_hw_cmds_v5(void)
 161{
 162        return &s5p_mfc_cmds_v5;
 163}
 164