drm/amd/display: Hook up calls to do stereo mux and dig programming to stereo control...
authorMurton Liu <murton.liu@amd.com>
Tue, 25 Jun 2019 15:15:09 +0000 (11:15 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 18 Jul 2019 19:27:25 +0000 (14:27 -0500)
[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>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c
drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c
drivers/gpu/drm/amd/display/include/gpio_service_interface.h

index 32fd9184ef224a5e6e3c90a8c6ee2f1e43cd60b3..a8516deb5ac3864bf114d347993f168388ce6f16 100644 (file)
@@ -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)
index abc039b836d458a26e665e2f25dc47d4e25db8a0..b314fd2869ddc8d199cf05944e8c447cb2cbf053 100644 (file)
@@ -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
index 2118ea21d7e95082b267b387bf80a813c8ec44f3..89c958f00e9ab8ec0a9d2f55d98349e106349cf9 100644 (file)
@@ -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,
index 32aa47a04a0dae71913ed75e57303459ec25ce88..5711f30cf848474730371c199203119b10d8ab02 100644 (file)
@@ -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
index a7fab44f66b666dc5d64d3a64a95f2894a15bb3e..5b02db13eb2afbe43c83049ac05b38b38ce9a0b5 100644 (file)
@@ -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(
index f40259bade400de83ca148e4cd1c8f984af5a59e..9c55d247227ea5fb5098679da77a74f55a041e05 100644 (file)
@@ -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);