diff options
author | Murton Liu <murton.liu@amd.com> | 2019-06-25 17:15:09 +0200 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2019-07-18 21:27:25 +0200 |
commit | c2cd9d04ecf0f26fb472ffbd8274a55c05df0ffb (patch) | |
tree | a44c5a9a1da65de9e87948078266982e15e8401d | |
parent | drm/amd/display: 3.2.41 (diff) | |
download | linux-c2cd9d04ecf0f26fb472ffbd8274a55c05df0ffb.tar.xz linux-c2cd9d04ecf0f26fb472ffbd8274a55c05df0ffb.zip |
drm/amd/display: Hook up calls to do stereo mux and dig programming to stereo control interface
[Why]
Implementation of stereo mux register is complete, but unused. Need to
call functions to write relevant configs.
[How]
Add function to write stereo config for enable/disable case and call in
stereo control interface.
Signed-off-by: Murton Liu <murton.liu@amd.com>
Reviewed-by: Aric Cyr <Aric.Cyr@amd.com>
Acked-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
6 files changed, 186 insertions, 3 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c index 32fd9184ef22..a8516deb5ac3 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc.c @@ -1236,6 +1236,53 @@ void dc_release_state(struct dc_state *context) kref_put(&context->refcount, dc_state_free); } +bool dc_set_generic_gpio_for_stereo(bool enable, + struct gpio_service *gpio_service) +{ + enum gpio_result gpio_result = GPIO_RESULT_NON_SPECIFIC_ERROR; + struct gpio_pin_info pin_info; + struct gpio *generic; + struct gpio_generic_mux_config *config = kzalloc(sizeof(struct gpio_generic_mux_config), + GFP_KERNEL); + + pin_info = dal_gpio_get_generic_pin_info(gpio_service, GPIO_ID_GENERIC, 0); + + if (pin_info.mask == 0xFFFFFFFF || pin_info.offset == 0xFFFFFFFF) { + kfree(config); + return false; + } else { + generic = dal_gpio_service_create_generic_mux( + gpio_service, + pin_info.offset, + pin_info.mask); + } + + if (!generic) { + kfree(config); + return false; + } + + gpio_result = dal_gpio_open(generic, GPIO_MODE_OUTPUT); + + config->enable_output_from_mux = enable; + config->mux_select = GPIO_SIGNAL_SOURCE_PASS_THROUGH_STEREO_SYNC; + + if (gpio_result == GPIO_RESULT_OK) + gpio_result = dal_mux_setup_config(generic, config); + + if (gpio_result == GPIO_RESULT_OK) { + dal_gpio_close(generic); + dal_gpio_destroy_generic_mux(&generic); + kfree(config); + return true; + } else { + dal_gpio_close(generic); + dal_gpio_destroy_generic_mux(&generic); + kfree(config); + return false; + } +} + static bool is_surface_in_context( const struct dc_state *context, const struct dc_plane_state *plane_state) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index abc039b836d4..b314fd2869dd 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -852,6 +852,9 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info); +bool dc_set_generic_gpio_for_stereo(bool enable, + struct gpio_service *gpio_service); + /* * fast_validate: we return after determining if we can support the new state, * but before we populate the programming info diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c index 2118ea21d7e9..89c958f00e9a 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c @@ -2692,6 +2692,13 @@ static void dcn10_setup_stereo(struct pipe_ctx *pipe_ctx, struct dc *dc) dcn10_config_stereo_parameters(stream, &flags); + if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_SIDEBAND_FA) { + if (!dc_set_generic_gpio_for_stereo(true, dc->ctx->gpio_service)) + dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service); + } else { + dc_set_generic_gpio_for_stereo(false, dc->ctx->gpio_service); + } + pipe_ctx->stream_res.opp->funcs->opp_program_stereo( pipe_ctx->stream_res.opp, flags.PROGRAM_STEREO == 1 ? true:false, diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c index 32aa47a04a0d..5711f30cf848 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c @@ -31,6 +31,7 @@ #include "../hw_gpio.h" #include "../hw_ddc.h" #include "../hw_hpd.h" +#include "../hw_generic.h" #include "hw_factory_dcn10.h" @@ -121,6 +122,42 @@ static const struct ddc_sh_mask ddc_mask = { DDC_MASK_SH_LIST(_MASK) }; +#include "../generic_regs.h" + +/* set field name */ +#define SF_GENERIC(reg_name, field_name, post_fix)\ + .field_name = reg_name ## __ ## field_name ## post_fix + +#define generic_regs(id) \ +{\ + GENERIC_REG_LIST(id)\ +} + +static const struct generic_registers generic_regs[] = { + generic_regs(A), + generic_regs(B), +}; + +static const struct generic_sh_mask generic_shift[] = { + GENERIC_MASK_SH_LIST(__SHIFT, A), + GENERIC_MASK_SH_LIST(__SHIFT, B), +}; + +static const struct generic_sh_mask generic_mask[] = { + GENERIC_MASK_SH_LIST(_MASK, A), + GENERIC_MASK_SH_LIST(_MASK, B), +}; + +static void define_generic_registers(struct hw_gpio_pin *pin, uint32_t en) +{ + struct hw_generic *generic = HW_GENERIC_FROM_BASE(pin); + + generic->regs = &generic_regs[en]; + generic->shifts = &generic_shift[en]; + generic->masks = &generic_mask[en]; + generic->base.regs = &generic_regs[en].gpio; +} + static void define_ddc_registers( struct hw_gpio_pin *pin, uint32_t en) @@ -161,12 +198,13 @@ static void define_hpd_registers(struct hw_gpio_pin *pin, uint32_t en) static const struct hw_factory_funcs funcs = { .create_ddc_data = dal_hw_ddc_create, .create_ddc_clock = dal_hw_ddc_create, - .create_generic = NULL, + .create_generic = dal_hw_generic_create, .create_hpd = dal_hw_hpd_create, .create_sync = NULL, .create_gsl = NULL, .define_hpd_registers = define_hpd_registers, - .define_ddc_registers = define_ddc_registers + .define_ddc_registers = define_ddc_registers, + .define_generic_registers = define_generic_registers }; /* * dal_hw_factory_dcn10_init diff --git a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c index a7fab44f66b6..5b02db13eb2a 100644 --- a/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c +++ b/drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c @@ -141,6 +141,62 @@ struct gpio *dal_gpio_service_create_irq( return dal_gpio_create_irq(service, id, en); } +struct gpio *dal_gpio_service_create_generic_mux( + struct gpio_service *service, + uint32_t offset, + uint32_t mask) +{ + enum gpio_id id; + uint32_t en; + struct gpio *generic; + + if (mask == 1) + en = GPIO_GENERIC_A; + else if (mask == 0x00000100L) + en = GPIO_GENERIC_B; + else + return NULL; + + id = GPIO_ID_GENERIC; + + generic = dal_gpio_create( + service, id, en, GPIO_PIN_OUTPUT_STATE_DEFAULT); + + return generic; +} + +void dal_gpio_destroy_generic_mux( + struct gpio **mux) +{ + if (!mux || !*mux) { + ASSERT_CRITICAL(false); + return; + } + + dal_gpio_close(*mux); + dal_gpio_destroy(mux); + kfree(*mux); + + *mux = NULL; +} + +struct gpio_pin_info dal_gpio_get_generic_pin_info( + struct gpio_service *service, + enum gpio_id id, + uint32_t en) +{ + struct gpio_pin_info pin; + + if (service->translate.funcs->id_to_offset) { + service->translate.funcs->id_to_offset(id, en, &pin); + } else { + pin.mask = 0xFFFFFFFF; + pin.offset = 0xFFFFFFFF; + } + + return pin; +} + void dal_gpio_service_destroy( struct gpio_service **ptr) { @@ -165,6 +221,21 @@ void dal_gpio_service_destroy( *ptr = NULL; } +enum gpio_result dal_mux_setup_config( + struct gpio *mux, + struct gpio_generic_mux_config *config) +{ + struct gpio_config_data config_data; + + if (!config) + return GPIO_RESULT_INVALID_DATA; + + config_data.config.generic_mux = *config; + config_data.type = GPIO_CONFIG_TYPE_GENERIC_MUX; + + return dal_gpio_set_config(mux, &config_data); +} + /* * @brief * Private API. @@ -255,6 +326,7 @@ enum gpio_result dal_gpio_service_open( case GPIO_ID_GENERIC: pin = service->factory.funcs->create_generic( service->ctx, id, en); + service->factory.funcs->define_generic_registers(pin, en); break; case GPIO_ID_HPD: pin = service->factory.funcs->create_hpd( diff --git a/drivers/gpu/drm/amd/display/include/gpio_service_interface.h b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h index f40259bade40..9c55d247227e 100644 --- a/drivers/gpu/drm/amd/display/include/gpio_service_interface.h +++ b/drivers/gpu/drm/amd/display/include/gpio_service_interface.h @@ -51,13 +51,29 @@ struct gpio *dal_gpio_service_create_irq( uint32_t offset, uint32_t mask); +struct gpio *dal_gpio_service_create_generic_mux( + struct gpio_service *service, + uint32_t offset, + uint32_t mask); + +void dal_gpio_destroy_generic_mux( + struct gpio **mux); + +enum gpio_result dal_mux_setup_config( + struct gpio *mux, + struct gpio_generic_mux_config *config); + +struct gpio_pin_info dal_gpio_get_generic_pin_info( + struct gpio_service *service, + enum gpio_id id, + uint32_t en); + struct ddc *dal_gpio_create_ddc( struct gpio_service *service, uint32_t offset, uint32_t mask, struct gpio_ddc_hw_info *info); - void dal_gpio_destroy_ddc( struct ddc **ddc); |