/*
* Copyright 2012-15 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: AMD
*
*/
#include "dm_services.h"
#include "dce_calcs.h"
#include "dcn10_mem_input.h"
#include "reg_helper.h"
#include "basics/conversion.h"
#define REG(reg)\
mi->mi_regs->reg
#define CTX \
mi->base.ctx
#undef FN
#define FN(reg_name, field_name) \
mi->mi_shift->field_name, mi->mi_mask->field_name
static void dcn_mi_set_blank(struct mem_input *mem_input, bool blank)
{
struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input);
uint32_t blank_en = blank ? 1 : 0;
REG_UPDATE_2(DCHUBP_CNTL,
HUBP_BLANK_EN, blank_en,
HUBP_TTU_DISABLE, blank_en);
}
static void vready_workaround(struct mem_input *mem_input,
struct _vcs_dpi_display_pipe_dest_params_st *pipe_dest)
{
uint32_t value = 0;
struct dcn10_mem_input *mi = TO_DCN10_MEM_INPUT(mem_input);
/* set HBUBREQ_DEBUG_DB[12] = 1 */
value = REG_READ(HUBPREQ_DEBUG_DB);
/* hack mode disable */
value |= 0x100;
value &= ~0x1000;
if ((pipe_dest->vstartup_start - 2*(pipe_dest->vready_offset+pipe_dest->vupdate_width
+ pipe_dest->vupdate_offset) / pipe_dest->htotal) <= pipe_dest->vblank_end) {
/* if (eco_fix_needed(otg_global_sync_timing)
* set HBUBREQ_DEBUG_DB[12] = 1 */
value |= 0x1000;
}
REG_WRITE(HUBPREQ_DEBUG_DB, value);
}
static void program_tiling(
struct dcn10_mem_input *mi,
const union dc_tiling_info *info,
const enum surface_pixel_format pixel_format)
{
REG_UPDATE_6(DCSURF_ADDR_CONFIG,
NUM_PIPES, log_2(info->gfx9.num_pipes),
NUM_BANKS, log_2(info->gfx9.num_banks),
PIPE_INTERLEAVE, info->gfx9.pipe_interleave,
NUM_SE, log_2(info->gfx9.num_shader_engines),
NUM_RB_PER_SE, log_2(info->gfx9.num_rb_per_se),
MAX_COMPRESSED_FRAGS, log_2(info->gfx9.max_compressed_frags));
REG_UPDATE_4(DCSURF_TILING_CONFIG,
SW_MODE, info->gfx9.swizzle,
META_LINEAR, info->gfx9.meta_linear,
RB_ALIGNED, info->gfx9.rb_aligned,
PIPE_ALIGNED, info->gfx9.pipe_aligned);
}
static void program_size_and_rotation(
struct dcn10_mem_input *mi,
enum dc_rotation_angle rotation,
enum surface_pixel_format format,
const union plane_size *plane_size,
struct dc_plane_dcc_param *dcc,
bool horizontal_mirror)
{
uint32_t pitch, meta_pitch, pitch_c, meta_pitch_c, mirror;
/* Program data and meta surface pitch (calculation from addrlib)
* 444 or 420 luma
*/
if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN) {
pitch = plane_size->video.luma_pitch - 1;
meta_pitch = dcc->video.meta_pitch_l - 1;
pitch_c = plane_size->video.chroma_pitch - 1;
meta_pitch_c = dcc->video.meta_pitch_c - 1;
} else {
pitch = plane_size->grph.surface_pitch - 1;
meta_pitch = dcc->grph.meta_pitch - 1;
pitch_c = 0;
meta_pitch_c = 0;
}
if (!dcc->enable) {
meta_pitch = 0;
meta_pitch_c = 0;
}
REG_UPDATE_2(DCSURF_SURFACE_PITCH,
PITCH, pitch, META_PITCH, meta_pitch);
if (format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
REG_UPDATE_2(DCSURF_SURFACE_PITCH_C,
PITCH_C, pitch_c, META_PITCH_C, meta_pitch_c);
if (horizontal_mirror)
mirror = 1;
else
mirror = 0;
/* Program rotation angle and horz mirror - no mirror */
if (rotation == ROTATION_ANGLE_0)
REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
ROTATION_ANGLE, 0,
H_MIRROR_EN, mirror);
else if (rotation == ROTATION_ANGLE_90)
REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
ROTATION_ANGLE, 1,
H_MIRROR_EN, mirror);
else if (rotation == ROTATION_ANGLE_180)
REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
ROTATION_ANGLE, 2,
H_MIRROR_EN, mirror);
else if (rotation == ROTATION_ANGLE_270)
REG_UPDATE_2(DCSURF_SURFACE_CONFIG,
ROTATION_ANGLE, 3,
H_MIRROR_EN, mirror);
}
static void program_pixel_format(
struct dcn10_mem_input *mi,
enum