359 lines
9.8 KiB
C
359 lines
9.8 KiB
C
/**
|
|
* file vsp.h
|
|
* Author: Binglin Chen <binglin.chen@intel.com>
|
|
*
|
|
*/
|
|
|
|
/**************************************************************************
|
|
*
|
|
* Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
**************************************************************************/
|
|
|
|
#ifndef _VSP_H_
|
|
#define _VSP_H_
|
|
|
|
#include "psb_drv.h"
|
|
#include "vsp_fw.h"
|
|
|
|
/* reg define */
|
|
#define SP1_SP_DMEM_IP 0x70000
|
|
|
|
/* processor */
|
|
#define SP0_SP_REG_BASE 0x000000
|
|
#define SP1_SP_REG_BASE 0x050000
|
|
#define VP0_SP_REG_BASE 0x080000
|
|
#define VP1_SP_REG_BASE 0x0C0000
|
|
#define MEA_SP_REG_BASE 0x100000
|
|
|
|
/* SP stat_ctrl */
|
|
#define SP_STAT_AND_CTRL_REG 0x0
|
|
#define SP_STAT_AND_CTRL_REG_RESET_FLAG 0
|
|
#define SP_STAT_AND_CTRL_REG_START_FLAG 1
|
|
#define SP_STAT_AND_CTRL_REG_BREAK_FLAG 2
|
|
#define SP_STAT_AND_CTRL_REG_RUN_FLAG 3
|
|
#define SP_STAT_AND_CTRL_REG_BROKEN_FLAG 4
|
|
#define SP_STAT_AND_CTRL_REG_READY_FLAG 5
|
|
#define SP_STAT_AND_CTRL_REG_SLEEP_FLAG 6
|
|
#define SP_STAT_AND_CTRL_REG_ICACHE_INVALID_FLAG 0xC
|
|
#define SP_STAT_AND_CTRL_REG_ICACHE_PREFETCH_FLAG 0xD
|
|
|
|
/* offsets of registers in processors */
|
|
#define VSP_STAT_CTRL_REG_OFFSET 0x00000
|
|
#define VSP_START_PC_REG_OFFSET 0x00004
|
|
#define VSP_ICACHE_BASE_REG_OFFSET 0x00010
|
|
|
|
#define SP_BASE_ADDR_REG (0x1 * 4)
|
|
|
|
#define SP_CFG_PMEM_MASTER 0x10
|
|
|
|
/* MMU */
|
|
#define MMU_INVALID 0x1B0000
|
|
#define MMU_TABLE_ADDR 0x1B0004
|
|
|
|
/* IRQ controller */
|
|
#define VSP_IRQ_REG_BASE 0x190000
|
|
#define VSP_IRQ_CTRL_IRQ_EDGE 0x0
|
|
#define VSP_IRQ_CTRL_IRQ_MASK 0x4
|
|
#define VSP_IRQ_CTRL_IRQ_STATUS 0x8
|
|
#define VSP_IRQ_CTRL_IRQ_CLR 0xC
|
|
#define VSP_IRQ_CTRL_IRQ_ENB 0x10
|
|
#define VSP_IRQ_CTRL_IRQ_LEVEL_PULSE 0x14
|
|
|
|
#define VSP_SP0_IRQ_SHIFT 0x7
|
|
#define VSP_SP1_IRQ_SHIFT 0x8
|
|
|
|
#define VSP_CONFIG_REG_SDRAM_BASE 0x1A0000
|
|
#define VSP_CONFIG_REG_START 0x8
|
|
|
|
#define VSP_FIRMWARE_MEM_ALIGNMENT 4096
|
|
/* #define VP8_ENC_DEBUG 1 */
|
|
|
|
#define MAX_VP8_CONTEXT_NUM 3
|
|
#define MAX_VPP_CONTEXT_NUM 1
|
|
|
|
static const unsigned int vsp_processor_base[] = {
|
|
SP0_SP_REG_BASE,
|
|
SP1_SP_REG_BASE,
|
|
VP0_SP_REG_BASE,
|
|
VP1_SP_REG_BASE,
|
|
MEA_SP_REG_BASE
|
|
};
|
|
|
|
/* help macro */
|
|
#define MM_VSP_WRITE32(base, offset, value) \
|
|
do { \
|
|
*((uint32_t *)((unsigned char *)(dev_priv->vsp_reg) \
|
|
+ base + offset)) = value; \
|
|
} while (0)
|
|
|
|
#define MM_VSP_READ32(base, offset, pointer) \
|
|
do { \
|
|
*(pointer) = \
|
|
*((uint32_t *)((unsigned char *) \
|
|
(dev_priv->vsp_reg) \
|
|
+ base + offset)); \
|
|
} while (0)
|
|
|
|
#define SP1_DMEM_WRITE32(offset, value) \
|
|
MM_VSP_WRITE32(SP1_SP_DMEM_IP, offset, value)
|
|
#define SP1_DMEM_READ32(offset, pointer) \
|
|
MM_VSP_READ32(SP1_SP_DMEM_IP, offset, pointer)
|
|
|
|
#define SP_REG_WRITE32(offset, value, processor) \
|
|
do { \
|
|
MM_VSP_WRITE32(vsp_processor_base[processor], offset, value); \
|
|
} while (0)
|
|
|
|
#define SP_REG_READ32(offset, pointer, processor) \
|
|
do { \
|
|
MM_VSP_READ32(vsp_processor_base[processor], offset, pointer); \
|
|
} while (0)
|
|
|
|
|
|
#define SP0_REG_WRITE32(offset, value) \
|
|
MM_VSP_WRITE32(SP0_SP_REG_BASE, offset, value)
|
|
#define SP0_REG_READ32(offset, pointer) \
|
|
MM_VSP_READ32(SP0_SP_REG_BASE, offset, pointer)
|
|
|
|
#define SP1_REG_WRITE32(offset, value) \
|
|
MM_VSP_WRITE32(SP1_SP_REG_BASE, offset, value)
|
|
#define SP1_REG_READ32(offset, pointer) \
|
|
MM_READ32(SP1_SP_REG_BASE, offset, pointer)
|
|
|
|
#define CONFIG_REG_WRITE32(offset, value) \
|
|
MM_VSP_WRITE32(VSP_CONFIG_REG_SDRAM_BASE, ((offset) * 4), value)
|
|
#define CONFIG_REG_READ32(offset, pointer) \
|
|
MM_VSP_READ32(VSP_CONFIG_REG_SDRAM_BASE, ((offset) * 4), pointer)
|
|
|
|
#define PAGE_TABLE_SHIFT PAGE_SHIFT
|
|
#define INVALID_MMU MM_VSP_WRITE32(0, MMU_INVALID, 0x1)
|
|
#define SET_MMU_PTD(address) \
|
|
do { \
|
|
MM_VSP_WRITE32(0, MMU_TABLE_ADDR, address); \
|
|
} while (0)
|
|
|
|
#define VSP_SET_FLAG(val, offset) \
|
|
((val) = ((val) | (0x1 << (offset))))
|
|
#define VSP_CLEAR_FLAG(val, offset) \
|
|
((val) = ((val) & (~(0x1 << (offset)))))
|
|
#define VSP_READ_FLAG(val, offset) \
|
|
(((val) & (0x1 << (offset))) >> (offset))
|
|
#define VSP_REVERT_FLAG(val, offset) \
|
|
((val) = (val ^ (0x1 << (offset))))
|
|
|
|
#define IRQ_REG_WRITE32(offset, value) \
|
|
MM_VSP_WRITE32(VSP_IRQ_REG_BASE, offset, value)
|
|
#define IRQ_REG_READ32(offset, pointer) \
|
|
MM_VSP_READ32(VSP_IRQ_REG_BASE, offset, pointer)
|
|
|
|
#define VSP_NEW_PMSTATE(drm_dev, vsp_priv, new_state) \
|
|
do { \
|
|
vsp_priv->pmstate = new_state; \
|
|
sysfs_notify_dirent(vsp_priv->sysfs_pmstate); \
|
|
PSB_DEBUG_PM("VSP: %s\n", \
|
|
(new_state == PSB_PMSTATE_POWERUP) ? "powerup" \
|
|
: ((new_state == PSB_PMSTATE_POWERDOWN) ? "powerdown" \
|
|
: "clockgated")); \
|
|
} while (0)
|
|
|
|
extern int drm_vsp_pmpolicy;
|
|
|
|
/* The status of vsp hardware */
|
|
enum vsp_power_state {
|
|
VSP_STATE_HANG = -1,
|
|
VSP_STATE_DOWN = 0,
|
|
VSP_STATE_SUSPEND,
|
|
VSP_STATE_IDLE,
|
|
VSP_STATE_ACTIVE
|
|
};
|
|
|
|
/* The status of firmware */
|
|
enum vsp_firmware_state {
|
|
VSP_FW_NONE = 0,
|
|
VSP_FW_LOADED
|
|
};
|
|
|
|
#define VSP_CONFIG_SIZE 16
|
|
|
|
enum vsp_irq_reg {
|
|
VSP_IRQ_REG_EDGE = 0,
|
|
VSP_IRQ_REG_MASK = 1,
|
|
VSP_IRQ_REG_STATUS = 2,
|
|
VSP_IRQ_REG_CLR = 3,
|
|
VSP_IRQ_REG_ENB = 4,
|
|
VSP_IRQ_REG_PULSE = 5,
|
|
VSP_IRQ_REG_SIZE
|
|
};
|
|
|
|
enum vsp_context_num {
|
|
VSP_CONTEXT_NUM_VPP = 0,
|
|
VSP_CONTEXT_NUM_VP8 = 1,
|
|
VSP_CONTEXT_NUM_MAX = 3
|
|
};
|
|
|
|
enum vsp_fw_type {
|
|
VSP_FW_TYPE_VPP,
|
|
VSP_FW_TYPE_VP8
|
|
};
|
|
|
|
struct vsp_private {
|
|
struct drm_device *dev;
|
|
uint32_t current_sequence;
|
|
|
|
int fw_loaded;
|
|
int vsp_state;
|
|
|
|
spinlock_t lock;
|
|
|
|
unsigned int cmd_queue_size;
|
|
unsigned int ack_queue_size;
|
|
|
|
struct ttm_buffer_object *cmd_queue_bo;
|
|
unsigned int cmd_queue_sz;
|
|
struct ttm_bo_kmap_obj cmd_kmap;
|
|
struct vss_command_t *cmd_queue;
|
|
|
|
struct ttm_buffer_object *ack_queue_bo;
|
|
unsigned int ack_queue_sz;
|
|
struct ttm_bo_kmap_obj ack_kmap;
|
|
struct vss_response_t *ack_queue;
|
|
|
|
struct ttm_buffer_object *setting_bo;
|
|
struct ttm_bo_kmap_obj setting_kmap;
|
|
struct vsp_settings_t *setting;
|
|
|
|
struct vsp_secure_boot_header boot_header;
|
|
struct vsp_multi_app_blob_data ma_header;
|
|
|
|
struct vsp_ctrl_reg *ctrl;
|
|
|
|
unsigned int pmstate;
|
|
struct sysfs_dirent *sysfs_pmstate;
|
|
|
|
uint64_t vss_cc_acc;
|
|
|
|
unsigned int saved_config_regs[VSP_CONFIG_SIZE];
|
|
|
|
/* lock for vsp command */
|
|
struct mutex vsp_mutex;
|
|
|
|
/* pm suspend wq */
|
|
struct delayed_work vsp_suspend_wq;
|
|
|
|
/* irq tasklet */
|
|
struct delayed_work vsp_irq_wq;
|
|
|
|
/* the number of cmd will send to VSP */
|
|
int vsp_cmd_num;
|
|
|
|
/* save the address of vp8 cmd_buffer for now */
|
|
struct VssVp8encPictureParameterBuffer *vp8_encode_frame_cmd;
|
|
struct ttm_bo_kmap_obj vp8_encode_frame__kmap;
|
|
|
|
/* For VP8 dual encoding */
|
|
struct file *vp8_filp[4];
|
|
int context_vp8_num;
|
|
|
|
/* The context number of VPP */
|
|
int context_vpp_num;
|
|
|
|
/*
|
|
* to fix problem when CTRL+C vp8 encoding *
|
|
* save VssVp8encEncodeFrameCommand cmd numbers *
|
|
* */
|
|
int vp8_cmd_num;
|
|
|
|
struct vss_command_t seq_cmd;
|
|
|
|
/* to save the last sequence */
|
|
uint32_t last_sequence;
|
|
|
|
/* VPP pnp usage */
|
|
unsigned long cmd_submit_time;
|
|
int acc_num_cmd;
|
|
int force_flush_cmd;
|
|
int delayed_burst_cnt;
|
|
struct delayed_work vsp_cmd_submit_check_wq;
|
|
|
|
/* Composer related */
|
|
uint32_t compose_fence;
|
|
};
|
|
|
|
extern int vsp_init(struct drm_device *dev);
|
|
extern int vsp_deinit(struct drm_device *dev);
|
|
|
|
extern int vsp_reset(struct drm_psb_private *dev_priv);
|
|
|
|
extern int vsp_init_fw(struct drm_device *dev);
|
|
extern int vsp_setup_fw(struct drm_psb_private *dev_priv);
|
|
|
|
extern void vsp_enableirq(struct drm_device *dev);
|
|
extern void vsp_disableirq(struct drm_device *dev);
|
|
|
|
extern bool vsp_interrupt(void *pvData);
|
|
|
|
extern int vsp_cmdbuf_vpp(struct drm_file *priv,
|
|
struct list_head *validate_list,
|
|
uint32_t fence_type,
|
|
struct drm_psb_cmdbuf_arg *arg,
|
|
struct ttm_buffer_object *cmd_buffer,
|
|
struct psb_ttm_fence_rep *fence_arg);
|
|
|
|
extern bool vsp_fence_poll(struct drm_device *dev);
|
|
|
|
extern int vsp_new_context(struct drm_device *dev, struct file *filp, int ctx_type);
|
|
extern void vsp_rm_context(struct drm_device *dev, struct file *filp, int ctx_type);
|
|
extern uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver);
|
|
|
|
extern int psb_vsp_save_context(struct drm_device *dev);
|
|
extern int psb_vsp_restore_context(struct drm_device *dev);
|
|
extern int psb_check_vsp_idle(struct drm_device *dev);
|
|
|
|
void vsp_init_function(struct drm_psb_private *dev_priv);
|
|
void vsp_continue_function(struct drm_psb_private *dev_priv);
|
|
int vsp_resume_function(struct drm_psb_private *dev_priv);
|
|
|
|
extern int psb_vsp_dump_info(struct drm_psb_private *dev_priv);
|
|
|
|
extern void psb_powerdown_vsp(struct work_struct *work);
|
|
extern void vsp_irq_task(struct work_struct *work);
|
|
extern void vsp_cmd_submit_check(struct work_struct *work);
|
|
|
|
static inline
|
|
unsigned int vsp_is_idle(struct drm_psb_private *dev_priv,
|
|
unsigned int processor)
|
|
{
|
|
unsigned int reg, start_bit, idle_bit;
|
|
|
|
SP_REG_READ32(SP_STAT_AND_CTRL_REG, ®, processor);
|
|
start_bit = VSP_READ_FLAG(reg, SP_STAT_AND_CTRL_REG_START_FLAG);
|
|
idle_bit = VSP_READ_FLAG(reg, SP_STAT_AND_CTRL_REG_READY_FLAG);
|
|
|
|
return !start_bit && idle_bit;
|
|
}
|
|
|
|
static inline
|
|
unsigned int vsp_is_sleeping(struct drm_psb_private *dev_priv,
|
|
unsigned int processor)
|
|
{
|
|
unsigned int reg;
|
|
|
|
SP_REG_READ32(SP_STAT_AND_CTRL_REG, ®, processor);
|
|
return VSP_READ_FLAG(reg, SP_STAT_AND_CTRL_REG_SLEEP_FLAG);
|
|
}
|
|
#endif /* _VSP_H_ */
|