brintos

brintos / linux-shallow public Read only

0
0
Text · 6.1 KiB · caa6178 Raw
241 lines · c
1/*2 * Copyright 2022 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26/* FILE POLICY AND INTENDED USAGE:27 *28 * This file implements functions that manage basic HPD components such as gpio.29 * It also provides wrapper functions to execute HPD related programming. This30 * file only manages basic HPD functionality. It doesn't manage detection or31 * feature or signal specific HPD behaviors.32 */33#include "link_hpd.h"34#include "gpio_service_interface.h"35 36bool link_get_hpd_state(struct dc_link *link)37{38	uint32_t state = 0;39 40	dal_gpio_lock_pin(link->hpd_gpio);41	dal_gpio_get_value(link->hpd_gpio, &state);42	dal_gpio_unlock_pin(link->hpd_gpio);43 44	return state;45}46 47void link_enable_hpd(const struct dc_link *link)48{49	struct link_encoder *encoder = link->link_enc;50 51	if (encoder != NULL && encoder->funcs->enable_hpd != NULL)52		encoder->funcs->enable_hpd(encoder);53}54 55void link_disable_hpd(const struct dc_link *link)56{57	struct link_encoder *encoder = link->link_enc;58 59	if (encoder != NULL && encoder->funcs->enable_hpd != NULL)60		encoder->funcs->disable_hpd(encoder);61}62 63void link_enable_hpd_filter(struct dc_link *link, bool enable)64{65	struct gpio *hpd;66 67	if (enable) {68		link->is_hpd_filter_disabled = false;69		program_hpd_filter(link);70	} else {71		link->is_hpd_filter_disabled = true;72		/* Obtain HPD handle */73		hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id, link->ctx->gpio_service);74 75		if (!hpd)76			return;77 78		/* Setup HPD filtering */79		if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {80			struct gpio_hpd_config config;81 82			config.delay_on_connect = 0;83			config.delay_on_disconnect = 0;84 85			dal_irq_setup_hpd_filter(hpd, &config);86 87			dal_gpio_close(hpd);88		} else {89			ASSERT_CRITICAL(false);90		}91		/* Release HPD handle */92		dal_gpio_destroy_irq(&hpd);93	}94}95 96struct gpio *link_get_hpd_gpio(struct dc_bios *dcb,97			  struct graphics_object_id link_id,98			  struct gpio_service *gpio_service)99{100	enum bp_result bp_result;101	struct graphics_object_hpd_info hpd_info;102	struct gpio_pin_info pin_info;103 104	if (dcb->funcs->get_hpd_info(dcb, link_id, &hpd_info) != BP_RESULT_OK)105		return NULL;106 107	bp_result = dcb->funcs->get_gpio_pin_info(dcb,108		hpd_info.hpd_int_gpio_uid, &pin_info);109 110	if (bp_result != BP_RESULT_OK) {111		ASSERT(bp_result == BP_RESULT_NORECORD);112		return NULL;113	}114 115	return dal_gpio_service_create_irq(gpio_service,116					   pin_info.offset,117					   pin_info.mask);118}119 120bool query_hpd_status(struct dc_link *link, uint32_t *is_hpd_high)121{122	struct gpio *hpd_pin = link_get_hpd_gpio(123			link->ctx->dc_bios, link->link_id,124			link->ctx->gpio_service);125	if (!hpd_pin)126		return false;127 128	dal_gpio_open(hpd_pin, GPIO_MODE_INTERRUPT);129	dal_gpio_get_value(hpd_pin, is_hpd_high);130	dal_gpio_close(hpd_pin);131	dal_gpio_destroy_irq(&hpd_pin);132	return true;133}134 135enum hpd_source_id get_hpd_line(struct dc_link *link)136{137	struct gpio *hpd;138	enum hpd_source_id hpd_id;139 140		hpd_id = HPD_SOURCEID_UNKNOWN;141 142	hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,143			   link->ctx->gpio_service);144 145	if (hpd) {146		switch (dal_irq_get_source(hpd)) {147		case DC_IRQ_SOURCE_HPD1:148			hpd_id = HPD_SOURCEID1;149		break;150		case DC_IRQ_SOURCE_HPD2:151			hpd_id = HPD_SOURCEID2;152		break;153		case DC_IRQ_SOURCE_HPD3:154			hpd_id = HPD_SOURCEID3;155		break;156		case DC_IRQ_SOURCE_HPD4:157			hpd_id = HPD_SOURCEID4;158		break;159		case DC_IRQ_SOURCE_HPD5:160			hpd_id = HPD_SOURCEID5;161		break;162		case DC_IRQ_SOURCE_HPD6:163			hpd_id = HPD_SOURCEID6;164		break;165		default:166			BREAK_TO_DEBUGGER();167		break;168		}169 170		dal_gpio_destroy_irq(&hpd);171	}172 173	return hpd_id;174}175 176bool program_hpd_filter(const struct dc_link *link)177{178	bool result = false;179	struct gpio *hpd;180	int delay_on_connect_in_ms = 0;181	int delay_on_disconnect_in_ms = 0;182 183	if (link->is_hpd_filter_disabled)184		return false;185	/* Verify feature is supported */186	switch (link->connector_signal) {187	case SIGNAL_TYPE_DVI_SINGLE_LINK:188	case SIGNAL_TYPE_DVI_DUAL_LINK:189	case SIGNAL_TYPE_HDMI_TYPE_A:190		/* Program hpd filter */191		delay_on_connect_in_ms = 500;192		delay_on_disconnect_in_ms = 100;193		break;194	case SIGNAL_TYPE_DISPLAY_PORT:195	case SIGNAL_TYPE_DISPLAY_PORT_MST:196		/* Program hpd filter to allow DP signal to settle */197		/* 500:	not able to detect MST <-> SST switch as HPD is low for198		 * only 100ms on DELL U2413199		 * 0: some passive dongle still show aux mode instead of i2c200		 * 20-50: not enough to hide bouncing HPD with passive dongle.201		 * also see intermittent i2c read issues.202		 */203		delay_on_connect_in_ms = 80;204		delay_on_disconnect_in_ms = 0;205		break;206	case SIGNAL_TYPE_LVDS:207	case SIGNAL_TYPE_EDP:208	default:209		/* Don't program hpd filter */210		return false;211	}212 213	/* Obtain HPD handle */214	hpd = link_get_hpd_gpio(link->ctx->dc_bios, link->link_id,215			   link->ctx->gpio_service);216 217	if (!hpd)218		return result;219 220	/* Setup HPD filtering */221	if (dal_gpio_open(hpd, GPIO_MODE_INTERRUPT) == GPIO_RESULT_OK) {222		struct gpio_hpd_config config;223 224		config.delay_on_connect = delay_on_connect_in_ms;225		config.delay_on_disconnect = delay_on_disconnect_in_ms;226 227		dal_irq_setup_hpd_filter(hpd, &config);228 229		dal_gpio_close(hpd);230 231		result = true;232	} else {233		ASSERT_CRITICAL(false);234	}235 236	/* Release HPD handle */237	dal_gpio_destroy_irq(&hpd);238 239	return result;240}241