xref: /linux/drivers/gpu/drm/amd/display/dc/gpio/hw_hpd.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
14562236bSHarry Wentland /*
24562236bSHarry Wentland  * Copyright 2012-15 Advanced Micro Devices, Inc.
34562236bSHarry Wentland  *
44562236bSHarry Wentland  * Permission is hereby granted, free of charge, to any person obtaining a
54562236bSHarry Wentland  * copy of this software and associated documentation files (the "Software"),
64562236bSHarry Wentland  * to deal in the Software without restriction, including without limitation
74562236bSHarry Wentland  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
84562236bSHarry Wentland  * and/or sell copies of the Software, and to permit persons to whom the
94562236bSHarry Wentland  * Software is furnished to do so, subject to the following conditions:
104562236bSHarry Wentland  *
114562236bSHarry Wentland  * The above copyright notice and this permission notice shall be included in
124562236bSHarry Wentland  * all copies or substantial portions of the Software.
134562236bSHarry Wentland  *
144562236bSHarry Wentland  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
154562236bSHarry Wentland  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
164562236bSHarry Wentland  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
174562236bSHarry Wentland  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
184562236bSHarry Wentland  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
194562236bSHarry Wentland  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
204562236bSHarry Wentland  * OTHER DEALINGS IN THE SOFTWARE.
214562236bSHarry Wentland  *
224562236bSHarry Wentland  * Authors: AMD
234562236bSHarry Wentland  *
244562236bSHarry Wentland  */
254562236bSHarry Wentland 
264562236bSHarry Wentland #include "dm_services.h"
274562236bSHarry Wentland 
2891db9311SSu Sung Chung #include "include/gpio_interface.h"
294562236bSHarry Wentland #include "include/gpio_types.h"
304562236bSHarry Wentland #include "hw_gpio.h"
314562236bSHarry Wentland #include "hw_hpd.h"
324562236bSHarry Wentland 
334562236bSHarry Wentland #include "reg_helper.h"
344562236bSHarry Wentland #include "hpd_regs.h"
354562236bSHarry Wentland 
364562236bSHarry Wentland #undef FN
374562236bSHarry Wentland #define FN(reg_name, field_name) \
384562236bSHarry Wentland 	hpd->shifts->field_name, hpd->masks->field_name
394562236bSHarry Wentland 
404562236bSHarry Wentland #define CTX \
414562236bSHarry Wentland 	hpd->base.base.ctx
424562236bSHarry Wentland #define REG(reg)\
434562236bSHarry Wentland 	(hpd->regs->reg)
444562236bSHarry Wentland 
4591db9311SSu Sung Chung struct gpio;
4691db9311SSu Sung Chung 
dal_hw_hpd_destruct(struct hw_hpd * pin)474562236bSHarry Wentland static void dal_hw_hpd_destruct(
484562236bSHarry Wentland 	struct hw_hpd *pin)
494562236bSHarry Wentland {
504562236bSHarry Wentland 	dal_hw_gpio_destruct(&pin->base);
514562236bSHarry Wentland }
524562236bSHarry Wentland 
dal_hw_hpd_destroy(struct hw_gpio_pin ** ptr)53d9e32672SAnthony Koo static void dal_hw_hpd_destroy(
544562236bSHarry Wentland 	struct hw_gpio_pin **ptr)
554562236bSHarry Wentland {
564562236bSHarry Wentland 	struct hw_hpd *hpd = HW_HPD_FROM_BASE(*ptr);
574562236bSHarry Wentland 
58d9e32672SAnthony Koo 	dal_hw_hpd_destruct(hpd);
594562236bSHarry Wentland 
602004f45eSHarry Wentland 	kfree(hpd);
614562236bSHarry Wentland 
624562236bSHarry Wentland 	*ptr = NULL;
634562236bSHarry Wentland }
644562236bSHarry Wentland 
get_value(const struct hw_gpio_pin * ptr,uint32_t * value)654562236bSHarry Wentland static enum gpio_result get_value(
664562236bSHarry Wentland 	const struct hw_gpio_pin *ptr,
674562236bSHarry Wentland 	uint32_t *value)
684562236bSHarry Wentland {
694562236bSHarry Wentland 	struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr);
704562236bSHarry Wentland 	uint32_t hpd_delayed = 0;
714562236bSHarry Wentland 
724562236bSHarry Wentland 	/* in Interrupt mode we ask for SENSE bit */
734562236bSHarry Wentland 
744562236bSHarry Wentland 	if (ptr->mode == GPIO_MODE_INTERRUPT) {
754562236bSHarry Wentland 
764562236bSHarry Wentland 		REG_GET(int_status,
774562236bSHarry Wentland 			DC_HPD_SENSE_DELAYED, &hpd_delayed);
784562236bSHarry Wentland 
794562236bSHarry Wentland 		*value = hpd_delayed;
804562236bSHarry Wentland 		return GPIO_RESULT_OK;
814562236bSHarry Wentland 	}
824562236bSHarry Wentland 
834562236bSHarry Wentland 	/* in any other modes, operate as normal GPIO */
844562236bSHarry Wentland 
854562236bSHarry Wentland 	return dal_hw_gpio_get_value(ptr, value);
864562236bSHarry Wentland }
874562236bSHarry Wentland 
set_config(struct hw_gpio_pin * ptr,const struct gpio_config_data * config_data)884562236bSHarry Wentland static enum gpio_result set_config(
894562236bSHarry Wentland 	struct hw_gpio_pin *ptr,
904562236bSHarry Wentland 	const struct gpio_config_data *config_data)
914562236bSHarry Wentland {
924562236bSHarry Wentland 	struct hw_hpd *hpd = HW_HPD_FROM_BASE(ptr);
934562236bSHarry Wentland 
944562236bSHarry Wentland 	if (!config_data)
954562236bSHarry Wentland 		return GPIO_RESULT_INVALID_DATA;
964562236bSHarry Wentland 
974562236bSHarry Wentland 	REG_UPDATE_2(toggle_filt_cntl,
984562236bSHarry Wentland 		DC_HPD_CONNECT_INT_DELAY, config_data->config.hpd.delay_on_connect / 10,
994562236bSHarry Wentland 		DC_HPD_DISCONNECT_INT_DELAY, config_data->config.hpd.delay_on_disconnect / 10);
1004562236bSHarry Wentland 
1014562236bSHarry Wentland 	return GPIO_RESULT_OK;
1024562236bSHarry Wentland }
1034562236bSHarry Wentland 
1044562236bSHarry Wentland static const struct hw_gpio_pin_funcs funcs = {
105d9e32672SAnthony Koo 	.destroy = dal_hw_hpd_destroy,
1064562236bSHarry Wentland 	.open = dal_hw_gpio_open,
1074562236bSHarry Wentland 	.get_value = get_value,
1084562236bSHarry Wentland 	.set_value = dal_hw_gpio_set_value,
1094562236bSHarry Wentland 	.set_config = set_config,
1104562236bSHarry Wentland 	.change_mode = dal_hw_gpio_change_mode,
1114562236bSHarry Wentland 	.close = dal_hw_gpio_close,
1124562236bSHarry Wentland };
1134562236bSHarry Wentland 
dal_hw_hpd_construct(struct hw_hpd * pin,enum gpio_id id,uint32_t en,struct dc_context * ctx)114d9e32672SAnthony Koo static void dal_hw_hpd_construct(
115d9e32672SAnthony Koo 	struct hw_hpd *pin,
1164562236bSHarry Wentland 	enum gpio_id id,
1174562236bSHarry Wentland 	uint32_t en,
1184562236bSHarry Wentland 	struct dc_context *ctx)
1194562236bSHarry Wentland {
120d9e32672SAnthony Koo 	dal_hw_gpio_construct(&pin->base, id, en, ctx);
121d9e32672SAnthony Koo 	pin->base.base.funcs = &funcs;
1224562236bSHarry Wentland }
1234562236bSHarry Wentland 
dal_hw_hpd_init(struct hw_hpd ** hw_hpd,struct dc_context * ctx,enum gpio_id id,uint32_t en)12491db9311SSu Sung Chung void dal_hw_hpd_init(
12591db9311SSu Sung Chung 	struct hw_hpd **hw_hpd,
1264562236bSHarry Wentland 	struct dc_context *ctx,
1274562236bSHarry Wentland 	enum gpio_id id,
1284562236bSHarry Wentland 	uint32_t en)
1294562236bSHarry Wentland {
130*82c94233SAlex Hung 	if (en > GPIO_DDC_LINE_MAX) {
1310e1c42fdSDave Airlie 		ASSERT_CRITICAL(false);
13291db9311SSu Sung Chung 		*hw_hpd = NULL;
1330e1c42fdSDave Airlie 	}
1340e1c42fdSDave Airlie 
13591db9311SSu Sung Chung 	*hw_hpd = kzalloc(sizeof(struct hw_hpd), GFP_KERNEL);
13691db9311SSu Sung Chung 	if (!*hw_hpd) {
1370e1c42fdSDave Airlie 		ASSERT_CRITICAL(false);
13891db9311SSu Sung Chung 		return;
1390e1c42fdSDave Airlie 	}
1400e1c42fdSDave Airlie 
141d9e32672SAnthony Koo 	dal_hw_hpd_construct(*hw_hpd, id, en, ctx);
1424562236bSHarry Wentland }
1434562236bSHarry Wentland 
dal_hw_hpd_get_pin(struct gpio * gpio)14491db9311SSu Sung Chung struct hw_gpio_pin *dal_hw_hpd_get_pin(struct gpio *gpio)
14591db9311SSu Sung Chung {
14691db9311SSu Sung Chung 	struct hw_hpd *hw_hpd = dal_gpio_get_hpd(gpio);
14791db9311SSu Sung Chung 
14891db9311SSu Sung Chung 	return &hw_hpd->base.base;
1494562236bSHarry Wentland }
150