/** * Function: * void program_overscan * * Purpose: Programs overscan border * Input: overscan * * Output: void */ static void program_overscan( struct dce110_transform *xfm110, const struct overscan_info *overscan) { uint32_t overscan_left_right = 0; uint32_t overscan_top_bottom = 0; set_reg_field_value(overscan_left_right, overscan->left, SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT); set_reg_field_value(overscan_left_right, overscan->right, SCLV_EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT); set_reg_field_value(overscan_top_bottom, overscan->top, SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP); set_reg_field_value(overscan_top_bottom, overscan->bottom, SCLV_EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM); dm_write_reg(xfm110->base.ctx, mmSCLV_EXT_OVERSCAN_LEFT_RIGHT, overscan_left_right); dm_write_reg(xfm110->base.ctx, mmSCLV_EXT_OVERSCAN_TOP_BOTTOM, overscan_top_bottom); }
/* * Function: * void setup_scaling_configuration * * Purpose: setup scaling mode : bypass, RGb, YCbCr and nummber of taps * Input: data * * Output: * void */ static bool setup_scaling_configuration( struct dce110_transform *xfm110, const struct scaler_data *data) { bool is_scaling_needed = false; struct dc_context *ctx = xfm110->base.ctx; uint32_t value = 0; if (data->taps.h_taps + data->taps.v_taps > 2) { set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE); set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN); is_scaling_needed = true; } else { set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); } if (data->taps.h_taps_c + data->taps.v_taps_c > 2) { set_reg_field_value(value, 1, SCLV_MODE, SCL_MODE_C); set_reg_field_value(value, 1, SCLV_MODE, SCL_PSCL_EN_C); is_scaling_needed = true; } else if (data->format != PIXEL_FORMAT_420BPP12) { set_reg_field_value( value, get_reg_field_value(value, SCLV_MODE, SCL_MODE), SCLV_MODE, SCL_MODE_C); set_reg_field_value( value, get_reg_field_value(value, SCLV_MODE, SCL_PSCL_EN), SCLV_MODE, SCL_PSCL_EN_C); } else { set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); } dm_write_reg(ctx, mmSCLV_MODE, value); value = 0; set_reg_field_value(value, data->taps.h_taps - 1, SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS); set_reg_field_value(value, data->taps.v_taps - 1, SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS); set_reg_field_value(value, data->taps.h_taps_c - 1, SCLV_TAP_CONTROL, SCL_H_NUM_OF_TAPS_C); set_reg_field_value(value, data->taps.v_taps_c - 1, SCLV_TAP_CONTROL, SCL_V_NUM_OF_TAPS_C); dm_write_reg(ctx, mmSCLV_TAP_CONTROL, value); value = 0; /* * 0 - Replaced out of bound pixels with black pixel * (or any other required color) * 1 - Replaced out of bound pixels with the edge pixel */ set_reg_field_value(value, 1, SCLV_CONTROL, SCL_BOUNDARY_MODE); dm_write_reg(ctx, mmSCLV_CONTROL, value); return is_scaling_needed; }
/** * set_truncation * 1) set truncation depth: 0 for 18 bpp or 1 for 24 bpp * 2) enable truncation * 3) HW remove 12bit FMT support for DCE8 power saving reason. */ static void set_truncation( struct dce80_opp *opp80, const struct bit_depth_reduction_params *params) { uint32_t value = 0; uint32_t addr = FMT_REG(mmFMT_BIT_DEPTH_CONTROL); /*Disable truncation*/ value = dm_read_reg(opp80->base.ctx, addr); set_reg_field_value(value, 0, FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); set_reg_field_value(value, 0, FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); set_reg_field_value(value, 0, FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); dm_write_reg(opp80->base.ctx, addr, value); /* no 10bpc trunc on DCE8*/ if (params->flags.TRUNCATE_ENABLED == 0 || params->flags.TRUNCATE_DEPTH == 2) return; /*Set truncation depth and Enable truncation*/ set_reg_field_value(value, 1, FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_EN); set_reg_field_value(value, params->flags.TRUNCATE_MODE, FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_MODE); set_reg_field_value(value, params->flags.TRUNCATE_DEPTH, FMT_BIT_DEPTH_CONTROL, FMT_TRUNCATE_DEPTH); dm_write_reg(opp80->base.ctx, addr, value); }
/* luma part */ static void program_pri_addr_l( struct dce_mem_input *mem_input110, PHYSICAL_ADDRESS_LOC address) { uint32_t value = 0; uint32_t temp = 0; /*high register MUST be programmed first*/ temp = address.high_part & UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L__GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L_MASK; set_reg_field_value(value, temp, UNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L); dm_write_reg( mem_input110->base.ctx, mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH_L, value); temp = 0; value = 0; temp = address.low_part >> UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L__GRPH_PRIMARY_SURFACE_ADDRESS_L__SHIFT; set_reg_field_value(value, temp, UNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, GRPH_PRIMARY_SURFACE_ADDRESS_L); dm_write_reg( mem_input110->base.ctx, mmUNP_GRPH_PRIMARY_SURFACE_ADDRESS_L, value); }
static void dce110_tg_v_program_blank_color(struct timing_generator *tg, const struct tg_color *black_color) { uint32_t addr = mmCRTCV_BLACK_COLOR; uint32_t value = dm_read_reg(tg->ctx, addr); set_reg_field_value( value, black_color->color_b_cb, CRTCV_BLACK_COLOR, CRTC_BLACK_COLOR_B_CB); set_reg_field_value( value, black_color->color_g_y, CRTCV_BLACK_COLOR, CRTC_BLACK_COLOR_G_Y); set_reg_field_value( value, black_color->color_r_cr, CRTCV_BLACK_COLOR, CRTC_BLACK_COLOR_R_CR); dm_write_reg(tg->ctx, addr, value); addr = mmCRTCV_BLANK_DATA_COLOR; dm_write_reg(tg->ctx, addr, value); }
static bool dce110_timing_generator_v_enable_crtc(struct timing_generator *tg) { /* * Set MASTER_UPDATE_MODE to 0 * This is needed for DRR, and also suggested to be default value by Syed. */ uint32_t value; value = 0; set_reg_field_value(value, 0, CRTCV_MASTER_UPDATE_MODE, MASTER_UPDATE_MODE); dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value); /* TODO: may want this on for looking for underflow */ value = 0; dm_write_reg(tg->ctx, mmCRTCV_MASTER_UPDATE_MODE, value); value = 0; set_reg_field_value(value, 1, CRTCV_MASTER_EN, CRTC_MASTER_EN); dm_write_reg(tg->ctx, mmCRTCV_MASTER_EN, value); return true; }
/* enable DP audio */ static void enable_dp_audio( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id) { const uint32_t addr = mmDP_SEC_CNTL + engine_offset[engine_id]; uint32_t value; /* Enable Audio packets */ value = dm_read_reg(hw_ctx->ctx, addr); set_reg_field_value(value, 1, DP_SEC_CNTL, DP_SEC_ASP_ENABLE); dm_write_reg(hw_ctx->ctx, addr, value); /* Program the ATP and AIP next */ set_reg_field_value(value, 1, DP_SEC_CNTL, DP_SEC_ATP_ENABLE); set_reg_field_value(value, 1, DP_SEC_CNTL, DP_SEC_AIP_ENABLE); dm_write_reg(hw_ctx->ctx, addr, value); /* Program STREAM_ENABLE after all the other enables. */ set_reg_field_value(value, 1, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE); dm_write_reg(hw_ctx->ctx, addr, value); }
void generic_write_indirect_reg(const struct dc_context *ctx, uint32_t addr_index, uint32_t addr_data, uint32_t index, uint32_t data) { dm_write_reg(ctx, addr_index, index); dm_write_reg(ctx, addr_data, data); }
void dce110_compressor_set_fbc_invalidation_triggers( struct compressor *compressor, uint32_t fbc_trigger) { /* Disable region hit event, FBC_MEMORY_REGION_MASK = 0 (bits 16-19) * for DCE 11 regions cannot be used - does not work with S/G */ uint32_t addr = mmFBC_CLIENT_REGION_MASK; uint32_t value = dm_read_reg(compressor->ctx, addr); set_reg_field_value( value, 0, FBC_CLIENT_REGION_MASK, FBC_MEMORY_REGION_MASK); dm_write_reg(compressor->ctx, addr, value); /* Setup events when to clear all CSM entries (effectively marking * current compressed data invalid) * For DCE 11 CSM metadata 11111 means - "Not Compressed" * Used as the initial value of the metadata sent to the compressor * after invalidation, to indicate that the compressor should attempt * to compress all chunks on the current pass. Also used when the chunk * is not successfully written to memory. * When this CSM value is detected, FBC reads from the uncompressed * buffer. Set events according to passed in value, these events are * valid for DCE11: * - bit 0 - display register updated * - bit 28 - memory write from any client except from MCIF * - bit 29 - CG static screen signal is inactive * In addition, DCE11.1 also needs to set new DCE11.1 specific events * that are used to trigger invalidation on certain register changes, * for example enabling of Alpha Compression may trigger invalidation of * FBC once bit is set. These events are as follows: * - Bit 2 - FBC_GRPH_COMP_EN register updated * - Bit 3 - FBC_SRC_SEL register updated * - Bit 4 - FBC_MIN_COMPRESSION register updated * - Bit 5 - FBC_ALPHA_COMP_EN register updated * - Bit 6 - FBC_ZERO_ALPHA_CHUNK_SKIP_EN register updated * - Bit 7 - FBC_FORCE_COPY_TO_COMP_BUF register updated */ addr = mmFBC_IDLE_FORCE_CLEAR_MASK; value = dm_read_reg(compressor->ctx, addr); set_reg_field_value( value, fbc_trigger | FBC_IDLE_FORCE_GRPH_COMP_EN | FBC_IDLE_FORCE_SRC_SEL_CHANGE | FBC_IDLE_FORCE_MIN_COMPRESSION_CHANGE | FBC_IDLE_FORCE_ALPHA_COMP_EN | FBC_IDLE_FORCE_ZERO_ALPHA_CHUNK_SKIP_EN | FBC_IDLE_FORCE_FORCE_COPY_TO_COMP_BUF, FBC_IDLE_FORCE_CLEAR_MASK, FBC_IDLE_FORCE_CLEAR_MASK); dm_write_reg(compressor->ctx, addr, value); }
static void program_urgency_watermark( const struct dc_context *ctx, const uint32_t urgency_addr, const uint32_t wm_addr, struct dce_watermarks marks_low, uint32_t total_dest_line_time_ns) { /* register value */ uint32_t urgency_cntl = 0; uint32_t wm_mask_cntl = 0; /*Write mask to enable reading/writing of watermark set A*/ wm_mask_cntl = dm_read_reg(ctx, wm_addr); set_reg_field_value(wm_mask_cntl, 1, DPGV0_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK); dm_write_reg(ctx, wm_addr, wm_mask_cntl); urgency_cntl = dm_read_reg(ctx, urgency_addr); set_reg_field_value( urgency_cntl, marks_low.a_mark, DPGV0_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK); set_reg_field_value( urgency_cntl, total_dest_line_time_ns, DPGV0_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK); dm_write_reg(ctx, urgency_addr, urgency_cntl); /*Write mask to enable reading/writing of watermark set B*/ wm_mask_cntl = dm_read_reg(ctx, wm_addr); set_reg_field_value(wm_mask_cntl, 2, DPGV0_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK); dm_write_reg(ctx, wm_addr, wm_mask_cntl); urgency_cntl = dm_read_reg(ctx, urgency_addr); set_reg_field_value(urgency_cntl, marks_low.b_mark, DPGV0_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK); set_reg_field_value(urgency_cntl, total_dest_line_time_ns, DPGV0_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK); dm_write_reg(ctx, urgency_addr, urgency_cntl); }
/* setup Azalia HW block */ static void setup_azalia( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id, enum signal_type signal, const struct audio_crtc_info *crtc_info, const struct audio_pll_info *pll_info, const struct audio_info *audio_info) { uint32_t speakers = 0; uint32_t channels = 0; if (audio_info == NULL) /* This should not happen.it does so we don't get BSOD*/ return; speakers = audio_info->flags.info.ALLSPEAKERS; channels = dal_audio_hw_ctx_speakers_to_channels( hw_ctx, audio_info->flags.speaker_flags).all; /* setup the audio stream source select (audio -> dig mapping) */ { const uint32_t addr = mmAFMT_AUDIO_SRC_CONTROL + engine_offset[engine_id]; uint32_t value = 0; /*convert one-based index to zero-based */ set_reg_field_value(value, FROM_BASE(hw_ctx)->azalia_stream_id - 1, AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT); dm_write_reg(hw_ctx->ctx, addr, value); } /* Channel allocation */ { const uint32_t addr = mmAFMT_AUDIO_PACKET_CONTROL2 + engine_offset[engine_id]; uint32_t value = dm_read_reg(hw_ctx->ctx, addr); set_reg_field_value(value, channels, AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE); dm_write_reg(hw_ctx->ctx, addr, value); } configure_azalia(hw_ctx, signal, crtc_info, audio_info); }
void dce110_compressor_enable_fbc( struct compressor *compressor, struct compr_addr_and_pitch_params *params) { struct dce110_compressor *cp110 = TO_DCE110_COMPRESSOR(compressor); if (compressor->options.bits.FBC_SUPPORT && (!dce110_compressor_is_fbc_enabled_in_hw(compressor, NULL))) { uint32_t addr; uint32_t value, misc_value; addr = mmFBC_CNTL; value = dm_read_reg(compressor->ctx, addr); set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); set_reg_field_value( value, params->inst, FBC_CNTL, FBC_SRC_SEL); dm_write_reg(compressor->ctx, addr, value); /* Keep track of enum controller_id FBC is attached to */ compressor->is_enabled = true; compressor->attached_inst = params->inst; cp110->offsets = reg_offsets[params->inst]; /* Toggle it as there is bug in HW */ set_reg_field_value(value, 0, FBC_CNTL, FBC_GRPH_COMP_EN); dm_write_reg(compressor->ctx, addr, value); /* FBC usage with scatter & gather for dce110 */ misc_value = dm_read_reg(compressor->ctx, mmFBC_MISC); set_reg_field_value(misc_value, 1, FBC_MISC, FBC_INVALIDATE_ON_ERROR); set_reg_field_value(misc_value, 1, FBC_MISC, FBC_DECOMPRESS_ERROR_CLEAR); set_reg_field_value(misc_value, 0x14, FBC_MISC, FBC_SLOW_REQ_INTERVAL); dm_write_reg(compressor->ctx, mmFBC_MISC, misc_value); /* Enable FBC */ set_reg_field_value(value, 1, FBC_CNTL, FBC_GRPH_COMP_EN); dm_write_reg(compressor->ctx, addr, value); wait_for_fbc_state_changed(cp110, true); } }
static bool hpd_ack( struct irq_service *irq_service, const struct irq_source_info *info) { uint32_t addr = info->status_reg; uint32_t value = dm_read_reg(irq_service->ctx, addr); uint32_t current_status = get_reg_field_value( value, HPD0_DC_HPD_INT_STATUS, DC_HPD_SENSE_DELAYED); dal_irq_service_ack_generic(irq_service, info); value = dm_read_reg(irq_service->ctx, info->enable_reg); set_reg_field_value( value, current_status ? 0 : 1, HPD0_DC_HPD_INT_CONTROL, DC_HPD_INT_POLARITY); dm_write_reg(irq_service->ctx, info->enable_reg, value); return true; }
void dce110_opp_power_on_regamma_lut_v( struct transform *xfm, bool power_on) { uint32_t value = dm_read_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL); set_reg_field_value( value, 0, DCFEV_MEM_PWR_CTRL, COL_MAN_GAMMA_CORR_MEM_PWR_FORCE); set_reg_field_value( value, power_on, DCFEV_MEM_PWR_CTRL, COL_MAN_GAMMA_CORR_MEM_PWR_DIS); set_reg_field_value( value, 0, DCFEV_MEM_PWR_CTRL, COL_MAN_INPUT_GAMMA_MEM_PWR_FORCE); set_reg_field_value( value, power_on, DCFEV_MEM_PWR_CTRL, COL_MAN_INPUT_GAMMA_MEM_PWR_DIS); dm_write_reg(xfm->ctx, mmDCFEV_MEM_PWR_CTRL, value); }
static void enable_afmt_clock( const struct hw_ctx_audio *hw_ctx, enum engine_id engine_id, bool enable_flag) { uint32_t engine_offs = engine_offset[engine_id]; uint32_t value; uint32_t count = 0; uint32_t enable = enable_flag ? 1:0; /* Enable Audio packets*/ value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs); /*enable AFMT clock*/ set_reg_field_value(value, enable, AFMT_CNTL, AFMT_AUDIO_CLOCK_EN); dm_write_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs, value); /*wait for AFMT clock to turn on, * the expectation is that this * should complete in 1-2 reads) */ do { /* Wait for 1us between subsequent register reads.*/ udelay(1); value = dm_read_reg(hw_ctx->ctx, mmAFMT_CNTL + engine_offs); } while (get_reg_field_value(value, AFMT_CNTL, AFMT_AUDIO_CLOCK_ON) != enable && count++ < 10); }
void dce80_stream_encoder_stop_dp_info_packets( struct stream_encoder *enc) { /* stop generic packets on DP */ struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); struct dc_context *ctx = enc110->base.ctx; uint32_t addr = LINK_REG(DP_SEC_CNTL); uint32_t value = dm_read_reg(ctx, addr); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP0_ENABLE); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP1_ENABLE); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP2_ENABLE); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_GSP3_ENABLE); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_AVI_ENABLE); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_MPG_ENABLE); set_reg_field_value(value, 0, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE); /* this register shared with audio info frame. * therefore we need to keep master enabled * if at least one of the fields is not 0 */ if (value) set_reg_field_value( value, 1, DP_SEC_CNTL, DP_SEC_STREAM_ENABLE); dm_write_reg(ctx, addr, value); }
static void dce110_timing_generator_v_set_overscan_color(struct timing_generator *tg, const struct tg_color *overscan_color) { struct dc_context *ctx = tg->ctx; uint32_t value = 0; uint32_t addr; set_reg_field_value( value, overscan_color->color_b_cb, CRTCV_OVERSCAN_COLOR, CRTC_OVERSCAN_COLOR_BLUE); set_reg_field_value( value, overscan_color->color_g_y, CRTCV_OVERSCAN_COLOR, CRTC_OVERSCAN_COLOR_GREEN); set_reg_field_value( value, overscan_color->color_r_cr, CRTCV_OVERSCAN_COLOR, CRTC_OVERSCAN_COLOR_RED); addr = mmCRTCV_OVERSCAN_COLOR; dm_write_reg(ctx, addr, value); }
static void setup_i2c_polling( struct dc_context *ctx, const uint32_t addr, bool enable_detect, bool detect_mode) { uint32_t value; value = dm_read_reg(ctx, addr); set_reg_field_value( value, enable_detect, DC_I2C_DDC1_SETUP, DC_I2C_DDC1_ENABLE); set_reg_field_value( value, enable_detect, DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_ENABLE); if (enable_detect) set_reg_field_value( value, detect_mode, DC_I2C_DDC1_SETUP, DC_I2C_DDC1_EDID_DETECT_MODE); dm_write_reg(ctx, addr, value); }
/* initialize HW state */ static void hw_initialize( const struct hw_ctx_audio *hw_ctx) { uint32_t stream_id = FROM_BASE(hw_ctx)->azalia_stream_id; uint32_t addr; /* we only need to program the following registers once, so we only do it for the first audio stream.*/ if (stream_id != FIRST_AUDIO_STREAM_ID) return; /* Suport R5 - 32khz * Suport R6 - 44.1khz * Suport R7 - 48khz */ addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES; { uint32_t value; value = dm_read_reg(hw_ctx->ctx, addr); set_reg_field_value(value, 0x70, AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES); dm_write_reg(hw_ctx->ctx, addr, value); } /*Keep alive bit to verify HW block in BU. */ addr = mmAZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES; { uint32_t value; value = dm_read_reg(hw_ctx->ctx, addr); set_reg_field_value(value, 1, AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP); set_reg_field_value(value, 1, AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS); dm_write_reg(hw_ctx->ctx, addr, value); } }
static void dce110_timing_generator_v_set_overscan_color_black( struct timing_generator *tg, const struct tg_color *color) { struct dc_context *ctx = tg->ctx; uint32_t addr; uint32_t value = 0; set_reg_field_value( value, color->color_b_cb, CRTC_OVERSCAN_COLOR, CRTC_OVERSCAN_COLOR_BLUE); set_reg_field_value( value, color->color_r_cr, CRTC_OVERSCAN_COLOR, CRTC_OVERSCAN_COLOR_RED); set_reg_field_value( value, color->color_g_y, CRTC_OVERSCAN_COLOR, CRTC_OVERSCAN_COLOR_GREEN); addr = mmCRTCV_OVERSCAN_COLOR; dm_write_reg(ctx, addr, value); addr = mmCRTCV_BLACK_COLOR; dm_write_reg(ctx, addr, value); /* This is desirable to have a constant DAC output voltage during the * blank time that is higher than the 0 volt reference level that the * DAC outputs when the NBLANK signal * is asserted low, such as for output to an analog TV. */ addr = mmCRTCV_BLANK_DATA_COLOR; dm_write_reg(ctx, addr, value); /* TO DO we have to program EXT registers and we need to know LB DATA * format because it is used when more 10 , i.e. 12 bits per color * * m_mmDxCRTC_OVERSCAN_COLOR_EXT * m_mmDxCRTC_BLACK_COLOR_EXT * m_mmDxCRTC_BLANK_DATA_COLOR_EXT */ }
/* setup stream encoder in dvi mode */ void dce80_stream_encoder_dvi_set_stream_attribute( struct stream_encoder *enc, struct dc_crtc_timing *crtc_timing, bool is_dual_link) { struct dce110_stream_encoder *enc110 = DCE110STRENC_FROM_STRENC(enc); struct dc_context *ctx = enc110->base.ctx; uint32_t addr = LINK_REG(TMDS_CNTL); uint32_t value = dm_read_reg(ctx, addr); struct bp_encoder_control cntl = {0}; cntl.action = ENCODER_CONTROL_SETUP; cntl.engine_id = enc110->base.id; cntl.signal = is_dual_link ? SIGNAL_TYPE_DVI_DUAL_LINK : SIGNAL_TYPE_DVI_SINGLE_LINK; cntl.enable_dp_audio = false; cntl.pixel_clock = crtc_timing->pix_clk_khz; cntl.lanes_number = (is_dual_link) ? LANE_COUNT_EIGHT : LANE_COUNT_FOUR; cntl.color_depth = crtc_timing->display_color_depth; if (enc110->base.bp->funcs->encoder_control( enc110->base.bp, &cntl) != BP_RESULT_OK) return; switch (crtc_timing->pixel_encoding) { case PIXEL_ENCODING_YCBCR422: set_reg_field_value(value, 1, TMDS_CNTL, TMDS_PIXEL_ENCODING); break; default: set_reg_field_value(value, 0, TMDS_CNTL, TMDS_PIXEL_ENCODING); break; } switch (crtc_timing->pixel_encoding) { case COLOR_DEPTH_101010: if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB) set_reg_field_value( value, 2, TMDS_CNTL, TMDS_COLOR_FORMAT); else set_reg_field_value( value, 0, TMDS_CNTL, TMDS_COLOR_FORMAT); break; default: set_reg_field_value(value, 0, TMDS_CNTL, TMDS_COLOR_FORMAT); break; } dm_write_reg(ctx, addr, value); }
static void enable(struct dce_mem_input *mem_input110) { uint32_t value = 0; value = dm_read_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE); set_reg_field_value(value, 1, UNP_GRPH_ENABLE, GRPH_ENABLE); dm_write_reg(mem_input110->base.ctx, mmUNP_GRPH_ENABLE, value); }
static void dce110_transform_v_set_scalerv_bypass(struct transform *xfm) { uint32_t addr = mmSCLV_MODE; uint32_t value = dm_read_reg(xfm->ctx, addr); set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE); set_reg_field_value(value, 0, SCLV_MODE, SCL_MODE_C); set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN); set_reg_field_value(value, 0, SCLV_MODE, SCL_PSCL_EN_C); dm_write_reg(xfm->ctx, addr, value); }
uint32_t generic_read_indirect_reg(const struct dc_context *ctx, uint32_t addr_index, uint32_t addr_data, uint32_t index) { uint32_t value = 0; dm_write_reg(ctx, addr_index, index); value = dm_read_reg(ctx, addr_data); return value; }
void dce110_allocate_mem_input_v( struct mem_input *mi, uint32_t h_total,/* for current stream */ uint32_t v_total,/* for current stream */ uint32_t pix_clk_khz,/* for current stream */ uint32_t total_stream_num) { uint32_t addr; uint32_t value; uint32_t pix_dur; if (pix_clk_khz != 0) { addr = mmDPGV0_PIPE_ARBITRATION_CONTROL1; value = dm_read_reg(mi->ctx, addr); pix_dur = 1000000000ULL / pix_clk_khz; set_reg_field_value( value, pix_dur, DPGV0_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION); dm_write_reg(mi->ctx, addr, value); addr = mmDPGV1_PIPE_ARBITRATION_CONTROL1; value = dm_read_reg(mi->ctx, addr); pix_dur = 1000000000ULL / pix_clk_khz; set_reg_field_value( value, pix_dur, DPGV1_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION); dm_write_reg(mi->ctx, addr, value); addr = mmDPGV0_PIPE_ARBITRATION_CONTROL2; value = 0x4000800; dm_write_reg(mi->ctx, addr, value); addr = mmDPGV1_PIPE_ARBITRATION_CONTROL2; value = 0x4000800; dm_write_reg(mi->ctx, addr, value); } }
static void dce110_timing_generator_v_set_early_control( struct timing_generator *tg, uint32_t early_cntl) { uint32_t regval; uint32_t address = mmCRTC_CONTROL; regval = dm_read_reg(tg->ctx, address); set_reg_field_value(regval, early_cntl, CRTCV_CONTROL, CRTC_HBLANK_EARLY_CONTROL); dm_write_reg(tg->ctx, address, regval); }
static void configure_regamma_mode(struct dce_transform *xfm_dce, uint32_t mode) { uint32_t value = 0; set_reg_field_value( value, mode, GAMMA_CORR_CONTROL, GAMMA_CORR_MODE); dm_write_reg(xfm_dce->base.ctx, mmGAMMA_CORR_CONTROL, 0); }
/* --- helpers --- */ static void write_indirect_azalia_reg( const struct hw_ctx_audio *hw_ctx, uint32_t reg_index, uint32_t reg_data) { uint32_t addr = 0; uint32_t value = 0; /* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */ { addr = FROM_BASE(hw_ctx)->az_mm_reg_offsets. azf0endpointx_azalia_f0_codec_endpoint_index; set_reg_field_value(value, reg_index, AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX); dm_write_reg(hw_ctx->ctx, addr, value); } /* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */ { addr = FROM_BASE(hw_ctx)->az_mm_reg_offsets. azf0endpointx_azalia_f0_codec_endpoint_data; value = 0; set_reg_field_value(value, reg_data, AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA); dm_write_reg(hw_ctx->ctx, addr, value); } dal_logger_write( hw_ctx->ctx->logger, LOG_MAJOR_HW_TRACE, LOG_MINOR_HW_TRACE_AUDIO, "AUDIO:write_indirect_azalia_reg: index: %u data: %u\n", reg_index, reg_data); }
static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) { int ret, i; mutex_lock(&dev->phy_mutex); dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0xc : 0x4); for (i = 0; i < DM_TIMEOUT; i++) { u8 tmp; udelay(1); ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp); if (ret < 0) goto out; if ((tmp & 1) == 0) break; } if (i == DM_TIMEOUT) { netdev_err(dev->net, "%s read timed out!\n", phy ? "phy" : "eeprom"); ret = -EIO; goto out; } dm_write_reg(dev, DM_SHARED_CTRL, 0x0); ret = dm_read(dev, DM_SHARED_DATA, 2, value); netdev_dbg(dev->net, "read shared %d 0x%02x returned 0x%04x, %d\n", phy, reg, *value, ret); out: mutex_unlock(&dev->phy_mutex); return ret; }
static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 value) { int ret, i; mutex_lock(&dev->phy_mutex); ret = dm_write(dev, DM_SHARED_DATA, 2, &value); if (ret < 0) goto out; dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12); for (i = 0; i < DM_TIMEOUT; i++) { u8 tmp; udelay(1); ret = dm_read_reg(dev, DM_SHARED_CTRL, &tmp); if (ret < 0) goto out; /* ready */ if ((tmp & 1) == 0) break; } if (i == DM_TIMEOUT) { netdev_err(dev->net, "%s write timed out!\n", phy ? "phy" : "eeprom"); ret = -EIO; goto out; } dm_write_reg(dev, DM_SHARED_CTRL, 0x0); out: mutex_unlock(&dev->phy_mutex); return ret; }