blob: 6cb63765ed0d6aa4765cfb944a2b1edcb7a1ffc6 [file] [log] [blame]
/**************************************************************************
*
* Copyright (c) 2007 Intel Corporation, Hillsboro, OR, USA
* Copyright (c) Imagination Technologies Limited, UK
*
* 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.
*
* Authors:
* Li Zeng <li.zeng@intel.com>
* Fei Jiang <fei.jiang@intel.com>
*
**************************************************************************/
#ifndef _PSB_MSVDX_H_
#define _PSB_MSVDX_H_
#ifdef CONFIG_DRM_VXD_BYT
#include "vxd_drv.h"
#else
#include "psb_drv.h"
#include "img_types.h"
#endif
#include "psb_msvdx_reg.h"
extern int drm_msvdx_pmpolicy;
extern int drm_msvdx_bottom_half;
extern int drm_msvdx_delay;
extern int hdmi_state;
extern int drm_psb_msvdx_tiling;
#define FIRMWAREID 0x014d42ab
#define GET_MSVDX_FREQUENCY(freq_code) ((1600 * 2)/((freq_code) + 1))
/* psb_mmu.c */
uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver);
/* psb_msvdxinit.c */
int psb_wait_for_register(struct drm_psb_private *dev_priv,
uint32_t offset, uint32_t value, uint32_t enable,
uint32_t poll_cnt, uint32_t timeout);
int psb_msvdx_init(struct drm_device *dev);
int psb_msvdx_uninit(struct drm_device *dev);
int psb_msvdx_core_reset(struct drm_psb_private *dev_priv);
int psb_msvdx_post_init(struct drm_device *dev);
/* TODO: psb_msvdx_reset is used for the case of fw loading by driver
* Later we can test if it can be removed. */
int psb_msvdx_reset(struct drm_psb_private *dev_priv);
int psb_msvdx_post_boot_init(struct drm_device *dev);
/* psb_msvdx.c */
int psb_msvdx_interrupt(void *pvData);
int psb_mtx_send(struct drm_psb_private *dev_priv, const void *pvMsg);
#if 0
void psb_msvdx_lockup(struct drm_psb_private *dev_priv,
int *msvdx_lockup, int *msvdx_idle);
#endif
int psb_check_msvdx_idle(struct drm_device *dev);
int psb_wait_msvdx_idle(struct drm_device *dev);
int psb_cmdbuf_video(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,
struct psb_video_ctx *msvdx_ctx);
int psb_msvdx_save_context(struct drm_device *dev);
int psb_msvdx_restore_context(struct drm_device *dev);
void psb_msvdx_check_reset_fw(struct drm_device *dev);
void psb_powerdown_msvdx(struct work_struct *work);
void psb_msvdx_flush_cmd_queue(struct drm_device *dev);
#ifdef CONFIG_SLICE_HEADER_PARSING
int psb_allocate_term_buf(struct drm_device *dev,
struct ttm_buffer_object **term_buf,
uint32_t *base_addr, unsigned long size);
#endif
int32_t msvdx_rendec_init_by_msg(struct drm_device *dev);
/* psb_msvdx_fw.c */
int32_t psb_msvdx_alloc_fw_bo(struct drm_psb_private *dev_priv);
int psb_setup_fw(struct drm_device *dev);
int psb_setup_msvdx(struct drm_device *dev);
/* Non-Optimal Invalidation is not default */
#define MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV 2
#define FW_VA_RENDER_HOST_INT 0x00004000
#define MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION 0x00000020
#define FW_DEVA_ERROR_DETECTED 0x08000000
/* There is no work currently underway on the hardware */
#define MSVDX_FW_STATUS_HW_IDLE 0x00000001
#define MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE 0x00000200
#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D0 \
(MSVDX_DEVICE_NODE_FLAGS_MMU_NONOPT_INV | \
MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION | \
MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE)
#define MSVDX_DEVICE_NODE_FLAGS_DEFAULT_D1 \
(MSVDX_DEVICE_NODE_FLAGS_MMU_HW_INVALIDATION | \
MSVDX_DEVICE_NODE_FLAG_BRN23154_BLOCK_ON_FE)
#define POULSBO_D0 0x5
#define POULSBO_D1 0x6
#define PSB_REVID_OFFSET 0x8
#define MTX_CODE_BASE (0x80900000)
#define MTX_DATA_BASE (0x82880000)
#define PC_START_ADDRESS (0x80900000)
#define MTX_CORE_CODE_MEM (0x10)
#define MTX_CORE_DATA_MEM (0x18)
#define RENDEC_A_SIZE (4 * 1024 * 1024)
#define RENDEC_B_SIZE (1024 * 1024)
#define TERMINATION_SIZE 48
#define MSVDX_RESET_NEEDS_REUPLOAD_FW (0x2)
#define MSVDX_RESET_NEEDS_INIT_FW (0x1)
/* HOST_BE_OPP parameters */
struct HOST_BE_OPP_PARAMS {
uint32_t handle; /* struct ttm_buffer_object * of REGIO */
uint32_t buffer_stride;
uint32_t buffer_size;
uint32_t picture_width_mb;
uint32_t size_mb;
};
typedef struct drm_psb_msvdx_frame_info {
uint32_t handle;
uint32_t surface_id;
uint32_t fence;
uint32_t buffer_stride;
uint32_t buffer_size;
uint32_t picture_width_mb;
uint32_t fw_status;
uint32_t size_mb;
drm_psb_msvdx_decode_status_t decode_status;
} drm_psb_msvdx_frame_info_t;
#define MAX_DECODE_BUFFERS (24)
#define PSB_MAX_EC_INSTANCE (4)
#define PSB_MSVDX_INVALID_FENCE (0xffffffff)
#define PSB_MSVDX_INVALID_OFFSET (0xffffffff)
#define PSB_MSVDX_EC_ROLLBACK (9)
struct psb_msvdx_ec_ctx {
struct ttm_object_file *tfile; /* protected by cmdbuf_mutex */
uint32_t context_id;
drm_psb_msvdx_frame_info_t frame_info[MAX_DECODE_BUFFERS];
drm_psb_msvdx_frame_info_t *cur_frame_info;
int frame_idx;
/* 12 render msg + 1 deblock msg
* 12 * 20 + 1 * 48 = 288;
*/
unsigned char unfenced_cmd[300];
uint32_t cmd_size;
uint32_t deblock_cmd_offset;
uint32_t fence;
drm_psb_msvdx_decode_status_t decode_status;
};
#ifdef CONFIG_ION
struct psb_ion_buffer {
struct list_head head;
struct dma_buf *psDmaBuf;
struct dma_buf_attachment *psAttachment;
struct sg_table *sg;
int fd;
};
#endif
/* MSVDX private structure */
struct msvdx_private {
struct drm_device *dev;
int msvdx_needs_reset;
unsigned int pmstate;
struct sysfs_dirent *sysfs_pmstate;
uint32_t msvdx_current_sequence;
uint32_t msvdx_last_sequence;
struct drm_psb_private *dev_priv;
/*
*MSVDX Rendec Memory
*/
struct ttm_buffer_object *ccb0;
uint32_t base_addr0;
struct ttm_buffer_object *ccb1;
uint32_t base_addr1;
struct ttm_buffer_object *fw;
uint32_t is_load;
uint32_t mtx_mem_size;
/*
*MSVDX tile regions
*/
uint32_t tile_region_start0;
uint32_t tile_region_end0;
uint32_t tile_region_start1;
uint32_t tile_region_end1;
/*
*msvdx command queue
*/
spinlock_t msvdx_lock;
struct mutex msvdx_mutex;
struct list_head msvdx_queue;
int msvdx_busy;
int rendec_init;
int msvdx_fw_loaded;
void *msvdx_fw;
int msvdx_fw_size;
uint32_t fw_b0_uploaded;
uint32_t msvdx_hw_busy;
uint32_t vec_ec_mem_data[5];
uint32_t vec_ec_mem_saved;
uint32_t psb_dash_access_ctrl;
uint32_t decoding_err;
uint32_t fw_loaded_by_punit;
drm_psb_msvdx_frame_info_t frame_info[MAX_DECODE_BUFFERS];
drm_psb_msvdx_decode_status_t decode_status;
uint32_t host_be_opp_enabled;
/*work for error concealment*/
struct work_struct ec_work;
struct ttm_object_file *tfile; /* protected by cmdbuf_mutex */
struct psb_msvdx_ec_ctx *msvdx_ec_ctx[PSB_MAX_EC_INSTANCE];
struct psb_msvdx_ec_ctx *cur_msvdx_ec_ctx;
uint32_t deblock_cmd_offset;
int num_cmd;
struct drm_video_displaying_frameinfo displaying_frame;
/* pm suspend wq */
struct delayed_work msvdx_suspend_wq;
struct tasklet_struct msvdx_tasklet;
/* protected by msvdx_mutex */
/* Current video context */
struct psb_video_ctx *msvdx_ctx;
/* previous vieo context */
struct psb_video_ctx *last_msvdx_ctx;
uint32_t pm_gating_count;
struct page *mmu_recover_page;
#ifdef CONFIG_SLICE_HEADER_PARSING
struct ttm_buffer_object *term_buf;
uint32_t term_buf_addr;
#endif
atomic_t slc_workaround_ctx;
#ifdef CONFIG_ION
struct list_head ion_buffers_list;
struct mutex ion_buf_list_lock;
#endif
};
struct psb_msvdx_cmd_queue {
struct list_head head;
void *cmd;
unsigned long cmd_size;
uint32_t sequence;
uint32_t msvdx_tile;
uint32_t host_be_opp_enabled;
uint32_t deblock_cmd_offset;
struct ttm_object_file *tfile;
struct psb_video_ctx *msvdx_ctx;
int frame_boundary; /* this command is frame end if true */
};
#ifdef CONFIG_VIDEO_MRFLD
struct psb_msvdx_ec_ctx *psb_msvdx_find_ec_ctx(
struct msvdx_private *msvdx_priv,
struct ttm_object_file *tfile,
void *cmd);
#endif
void psb_msvdx_clearirq(struct drm_device *dev);
void psb_msvdx_disableirq(struct drm_device *dev);
void psb_msvdx_enableirq(struct drm_device *dev);
#define MSVDX_NEW_PMSTATE(drm_dev, msvdx_priv, new_state) \
do { \
msvdx_priv->pmstate = new_state; \
if (new_state == PSB_PMSTATE_POWERDOWN) \
msvdx_priv->pm_gating_count++; \
sysfs_notify_dirent(msvdx_priv->sysfs_pmstate); \
PSB_DEBUG_PM("MSVDX: %s, power gating count 0x%08x\n", \
(new_state == PSB_PMSTATE_POWERUP) ? "powerup" \
: ((new_state == PSB_PMSTATE_POWERDOWN) ? "powerdown" \
: "clockgated"), msvdx_priv->pm_gating_count); \
} while (0)
#if 0
#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
extern void psb_schedule_watchdog(struct drm_psb_private *dev_priv);
extern void psb_watchdog_init(struct drm_psb_private *dev_priv);
extern void psb_watchdog_takedown(struct drm_psb_private *dev_priv);
#endif
void psb_msvdx_mtx_set_clocks(struct drm_device *dev, uint32_t clock_state);
extern int psb_submit_video_cmdbuf(struct drm_device *dev,
struct ttm_buffer_object *cmd_buffer,
unsigned long cmd_offset,
unsigned long cmd_size,
struct psb_video_ctx *msvdx_ctx,
uint32_t fence_flag);
void msvdx_powerdown_tasklet(unsigned long data);
int psb_msvdx_dequeue_send(struct drm_device *dev);
#endif