Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2012-15 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  * Authors: AMD
0023  *
0024  */
0025 
0026 #include "dm_services.h"
0027 
0028 #include "include/gpio_interface.h"
0029 #include "include/gpio_types.h"
0030 #include "hw_gpio.h"
0031 #include "hw_ddc.h"
0032 
0033 #include "reg_helper.h"
0034 #include "gpio_regs.h"
0035 
0036 
0037 #undef FN
0038 #define FN(reg_name, field_name) \
0039     ddc->shifts->field_name, ddc->masks->field_name
0040 
0041 #define CTX \
0042     ddc->base.base.ctx
0043 #define REG(reg)\
0044     (ddc->regs->reg)
0045 
0046 struct gpio;
0047 
0048 static void dal_hw_ddc_destruct(
0049     struct hw_ddc *pin)
0050 {
0051     dal_hw_gpio_destruct(&pin->base);
0052 }
0053 
0054 static void dal_hw_ddc_destroy(
0055     struct hw_gpio_pin **ptr)
0056 {
0057     struct hw_ddc *pin = HW_DDC_FROM_BASE(*ptr);
0058 
0059     dal_hw_ddc_destruct(pin);
0060 
0061     kfree(pin);
0062 
0063     *ptr = NULL;
0064 }
0065 
0066 static enum gpio_result set_config(
0067     struct hw_gpio_pin *ptr,
0068     const struct gpio_config_data *config_data)
0069 {
0070     struct hw_ddc *ddc = HW_DDC_FROM_BASE(ptr);
0071     struct hw_gpio *hw_gpio = NULL;
0072     uint32_t regval;
0073     uint32_t ddc_data_pd_en = 0;
0074     uint32_t ddc_clk_pd_en = 0;
0075     uint32_t aux_pad_mode = 0;
0076 
0077     hw_gpio = &ddc->base;
0078 
0079     if (hw_gpio == NULL) {
0080         ASSERT_CRITICAL(false);
0081         return GPIO_RESULT_NULL_HANDLE;
0082     }
0083 
0084     regval = REG_GET_3(gpio.MASK_reg,
0085             DC_GPIO_DDC1DATA_PD_EN, &ddc_data_pd_en,
0086             DC_GPIO_DDC1CLK_PD_EN, &ddc_clk_pd_en,
0087             AUX_PAD1_MODE, &aux_pad_mode);
0088 
0089     switch (config_data->config.ddc.type) {
0090     case GPIO_DDC_CONFIG_TYPE_MODE_I2C:
0091         /* On plug-in, there is a transient level on the pad
0092          * which must be discharged through the internal pull-down.
0093          * Enable internal pull-down, 2.5msec discharge time
0094          * is required for detection of AUX mode */
0095         if (hw_gpio->base.en != GPIO_DDC_LINE_VIP_PAD) {
0096             if (!ddc_data_pd_en || !ddc_clk_pd_en) {
0097 
0098                 REG_SET_2(gpio.MASK_reg, regval,
0099                         DC_GPIO_DDC1DATA_PD_EN, 1,
0100                         DC_GPIO_DDC1CLK_PD_EN, 1);
0101 
0102                 if (config_data->type ==
0103                         GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
0104                     msleep(3);
0105             }
0106         } else {
0107             uint32_t sda_pd_dis = 0;
0108             uint32_t scl_pd_dis = 0;
0109 
0110             REG_GET_2(gpio.MASK_reg,
0111                   DC_GPIO_SDA_PD_DIS, &sda_pd_dis,
0112                   DC_GPIO_SCL_PD_DIS, &scl_pd_dis);
0113 
0114             if (sda_pd_dis) {
0115                 REG_SET(gpio.MASK_reg, regval,
0116                         DC_GPIO_SDA_PD_DIS, 0);
0117 
0118                 if (config_data->type ==
0119                         GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
0120                     msleep(3);
0121             }
0122 
0123             if (!scl_pd_dis) {
0124                 REG_SET(gpio.MASK_reg, regval,
0125                         DC_GPIO_SCL_PD_DIS, 1);
0126 
0127                 if (config_data->type ==
0128                         GPIO_CONFIG_TYPE_I2C_AUX_DUAL_MODE)
0129                     msleep(3);
0130             }
0131         }
0132 
0133         if (aux_pad_mode) {
0134             /* let pins to get de-asserted
0135              * before setting pad to I2C mode */
0136             if (config_data->config.ddc.data_en_bit_present ||
0137                 config_data->config.ddc.clock_en_bit_present)
0138                 /* [anaumov] in DAL2, there was
0139                  * dc_service_delay_in_microseconds(2000); */
0140                 msleep(2);
0141 
0142             /* set the I2C pad mode */
0143             /* read the register again,
0144              * some bits may have been changed */
0145             REG_UPDATE(gpio.MASK_reg,
0146                     AUX_PAD1_MODE, 0);
0147         }
0148 
0149         if (ddc->regs->dc_gpio_aux_ctrl_5 != 0) {
0150                 REG_UPDATE(dc_gpio_aux_ctrl_5, DDC_PAD_I2CMODE, 1);
0151         }
0152         //set  DC_IO_aux_rxsel = 2'b01
0153         if (ddc->regs->phy_aux_cntl != 0) {
0154                 REG_UPDATE(phy_aux_cntl, AUX_PAD_RXSEL, 1);
0155         }
0156         return GPIO_RESULT_OK;
0157     case GPIO_DDC_CONFIG_TYPE_MODE_AUX:
0158         /* set the AUX pad mode */
0159         if (!aux_pad_mode) {
0160             REG_SET(gpio.MASK_reg, regval,
0161                     AUX_PAD1_MODE, 1);
0162         }
0163         if (ddc->regs->dc_gpio_aux_ctrl_5 != 0) {
0164             REG_UPDATE(dc_gpio_aux_ctrl_5,
0165                     DDC_PAD_I2CMODE, 0);
0166         }
0167 
0168         return GPIO_RESULT_OK;
0169     case GPIO_DDC_CONFIG_TYPE_POLL_FOR_CONNECT:
0170         if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
0171             (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
0172             REG_UPDATE_3(ddc_setup,
0173                 DC_I2C_DDC1_ENABLE, 1,
0174                 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
0175                 DC_I2C_DDC1_EDID_DETECT_MODE, 0);
0176             return GPIO_RESULT_OK;
0177         }
0178     break;
0179     case GPIO_DDC_CONFIG_TYPE_POLL_FOR_DISCONNECT:
0180         if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
0181             (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
0182             REG_UPDATE_3(ddc_setup,
0183                 DC_I2C_DDC1_ENABLE, 1,
0184                 DC_I2C_DDC1_EDID_DETECT_ENABLE, 1,
0185                 DC_I2C_DDC1_EDID_DETECT_MODE, 1);
0186             return GPIO_RESULT_OK;
0187         }
0188     break;
0189     case GPIO_DDC_CONFIG_TYPE_DISABLE_POLLING:
0190         if ((hw_gpio->base.en >= GPIO_DDC_LINE_DDC1) &&
0191             (hw_gpio->base.en <= GPIO_DDC_LINE_DDC_VGA)) {
0192             REG_UPDATE_2(ddc_setup,
0193                 DC_I2C_DDC1_ENABLE, 0,
0194                 DC_I2C_DDC1_EDID_DETECT_ENABLE, 0);
0195             return GPIO_RESULT_OK;
0196         }
0197     break;
0198     }
0199 
0200     BREAK_TO_DEBUGGER();
0201 
0202     return GPIO_RESULT_NON_SPECIFIC_ERROR;
0203 }
0204 
0205 static const struct hw_gpio_pin_funcs funcs = {
0206     .destroy = dal_hw_ddc_destroy,
0207     .open = dal_hw_gpio_open,
0208     .get_value = dal_hw_gpio_get_value,
0209     .set_value = dal_hw_gpio_set_value,
0210     .set_config = set_config,
0211     .change_mode = dal_hw_gpio_change_mode,
0212     .close = dal_hw_gpio_close,
0213 };
0214 
0215 static void dal_hw_ddc_construct(
0216     struct hw_ddc *ddc,
0217     enum gpio_id id,
0218     uint32_t en,
0219     struct dc_context *ctx)
0220 {
0221     dal_hw_gpio_construct(&ddc->base, id, en, ctx);
0222     ddc->base.base.funcs = &funcs;
0223 }
0224 
0225 void dal_hw_ddc_init(
0226     struct hw_ddc **hw_ddc,
0227     struct dc_context *ctx,
0228     enum gpio_id id,
0229     uint32_t en)
0230 {
0231     if ((en < GPIO_DDC_LINE_MIN) || (en > GPIO_DDC_LINE_MAX)) {
0232         ASSERT_CRITICAL(false);
0233         *hw_ddc = NULL;
0234     }
0235 
0236     *hw_ddc = kzalloc(sizeof(struct hw_ddc), GFP_KERNEL);
0237     if (!*hw_ddc) {
0238         ASSERT_CRITICAL(false);
0239         return;
0240     }
0241 
0242     dal_hw_ddc_construct(*hw_ddc, id, en, ctx);
0243 }
0244 
0245 struct hw_gpio_pin *dal_hw_ddc_get_pin(struct gpio *gpio)
0246 {
0247     struct hw_ddc *hw_ddc = dal_gpio_get_ddc(gpio);
0248 
0249     return &hw_ddc->base.base;
0250 }