summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMurton Liu <murton.liu@amd.com>2019-06-25 17:15:09 +0200
committerAlex Deucher <alexander.deucher@amd.com>2019-07-18 21:27:25 +0200
commitc2cd9d04ecf0f26fb472ffbd8274a55c05df0ffb (patch)
treea44c5a9a1da65de9e87948078266982e15e8401d
parentdrm/amd/display: 3.2.41 (diff)
downloadlinux-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>
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c47
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn10/hw_factory_dcn10.c42
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/gpio_service.c72
-rw-r--r--drivers/gpu/drm/amd/display/include/gpio_service_interface.h18
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);