Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2013 Red Hat
0004  * Author: Rob Clark <robdclark@gmail.com>
0005  */
0006 
0007 #include <linux/delay.h>
0008 #include <linux/gpio/consumer.h>
0009 #include <linux/pinctrl/consumer.h>
0010 
0011 #include "msm_kms.h"
0012 #include "hdmi.h"
0013 
0014 static void msm_hdmi_phy_reset(struct hdmi *hdmi)
0015 {
0016     unsigned int val;
0017 
0018     val = hdmi_read(hdmi, REG_HDMI_PHY_CTRL);
0019 
0020     if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
0021         /* pull low */
0022         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0023                 val & ~HDMI_PHY_CTRL_SW_RESET);
0024     } else {
0025         /* pull high */
0026         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0027                 val | HDMI_PHY_CTRL_SW_RESET);
0028     }
0029 
0030     if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
0031         /* pull low */
0032         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0033                 val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
0034     } else {
0035         /* pull high */
0036         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0037                 val | HDMI_PHY_CTRL_SW_RESET_PLL);
0038     }
0039 
0040     msleep(100);
0041 
0042     if (val & HDMI_PHY_CTRL_SW_RESET_LOW) {
0043         /* pull high */
0044         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0045                 val | HDMI_PHY_CTRL_SW_RESET);
0046     } else {
0047         /* pull low */
0048         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0049                 val & ~HDMI_PHY_CTRL_SW_RESET);
0050     }
0051 
0052     if (val & HDMI_PHY_CTRL_SW_RESET_PLL_LOW) {
0053         /* pull high */
0054         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0055                 val | HDMI_PHY_CTRL_SW_RESET_PLL);
0056     } else {
0057         /* pull low */
0058         hdmi_write(hdmi, REG_HDMI_PHY_CTRL,
0059                 val & ~HDMI_PHY_CTRL_SW_RESET_PLL);
0060     }
0061 }
0062 
0063 static void enable_hpd_clocks(struct hdmi *hdmi, bool enable)
0064 {
0065     const struct hdmi_platform_config *config = hdmi->config;
0066     struct device *dev = &hdmi->pdev->dev;
0067     int i, ret;
0068 
0069     if (enable) {
0070         for (i = 0; i < config->hpd_clk_cnt; i++) {
0071             if (config->hpd_freq && config->hpd_freq[i]) {
0072                 ret = clk_set_rate(hdmi->hpd_clks[i],
0073                            config->hpd_freq[i]);
0074                 if (ret)
0075                     dev_warn(dev,
0076                          "failed to set clk %s (%d)\n",
0077                          config->hpd_clk_names[i], ret);
0078             }
0079 
0080             ret = clk_prepare_enable(hdmi->hpd_clks[i]);
0081             if (ret) {
0082                 DRM_DEV_ERROR(dev,
0083                     "failed to enable hpd clk: %s (%d)\n",
0084                     config->hpd_clk_names[i], ret);
0085             }
0086         }
0087     } else {
0088         for (i = config->hpd_clk_cnt - 1; i >= 0; i--)
0089             clk_disable_unprepare(hdmi->hpd_clks[i]);
0090     }
0091 }
0092 
0093 int msm_hdmi_hpd_enable(struct drm_bridge *bridge)
0094 {
0095     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0096     struct hdmi *hdmi = hdmi_bridge->hdmi;
0097     const struct hdmi_platform_config *config = hdmi->config;
0098     struct device *dev = &hdmi->pdev->dev;
0099     uint32_t hpd_ctrl;
0100     int ret;
0101     unsigned long flags;
0102 
0103     ret = regulator_bulk_enable(config->hpd_reg_cnt, hdmi->hpd_regs);
0104     if (ret) {
0105         DRM_DEV_ERROR(dev, "failed to enable hpd regulators: %d\n", ret);
0106         goto fail;
0107     }
0108 
0109     ret = pinctrl_pm_select_default_state(dev);
0110     if (ret) {
0111         DRM_DEV_ERROR(dev, "pinctrl state chg failed: %d\n", ret);
0112         goto fail;
0113     }
0114 
0115     if (hdmi->hpd_gpiod)
0116         gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1);
0117 
0118     pm_runtime_get_sync(dev);
0119     enable_hpd_clocks(hdmi, true);
0120 
0121     msm_hdmi_set_mode(hdmi, false);
0122     msm_hdmi_phy_reset(hdmi);
0123     msm_hdmi_set_mode(hdmi, true);
0124 
0125     hdmi_write(hdmi, REG_HDMI_USEC_REFTIMER, 0x0001001b);
0126 
0127     /* enable HPD events: */
0128     hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
0129             HDMI_HPD_INT_CTRL_INT_CONNECT |
0130             HDMI_HPD_INT_CTRL_INT_EN);
0131 
0132     /* set timeout to 4.1ms (max) for hardware debounce */
0133     spin_lock_irqsave(&hdmi->reg_lock, flags);
0134     hpd_ctrl = hdmi_read(hdmi, REG_HDMI_HPD_CTRL);
0135     hpd_ctrl |= HDMI_HPD_CTRL_TIMEOUT(0x1fff);
0136 
0137     /* Toggle HPD circuit to trigger HPD sense */
0138     hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
0139             ~HDMI_HPD_CTRL_ENABLE & hpd_ctrl);
0140     hdmi_write(hdmi, REG_HDMI_HPD_CTRL,
0141             HDMI_HPD_CTRL_ENABLE | hpd_ctrl);
0142     spin_unlock_irqrestore(&hdmi->reg_lock, flags);
0143 
0144     return 0;
0145 
0146 fail:
0147     return ret;
0148 }
0149 
0150 void msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge)
0151 {
0152     struct hdmi *hdmi = hdmi_bridge->hdmi;
0153     const struct hdmi_platform_config *config = hdmi->config;
0154     struct device *dev = &hdmi->pdev->dev;
0155     int ret;
0156 
0157     /* Disable HPD interrupt */
0158     hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0);
0159 
0160     msm_hdmi_set_mode(hdmi, false);
0161 
0162     enable_hpd_clocks(hdmi, false);
0163     pm_runtime_put(dev);
0164 
0165     ret = pinctrl_pm_select_sleep_state(dev);
0166     if (ret)
0167         dev_warn(dev, "pinctrl state chg failed: %d\n", ret);
0168 
0169     ret = regulator_bulk_disable(config->hpd_reg_cnt, hdmi->hpd_regs);
0170     if (ret)
0171         dev_warn(dev, "failed to disable hpd regulator: %d\n", ret);
0172 }
0173 
0174 void msm_hdmi_hpd_irq(struct drm_bridge *bridge)
0175 {
0176     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0177     struct hdmi *hdmi = hdmi_bridge->hdmi;
0178     uint32_t hpd_int_status, hpd_int_ctrl;
0179 
0180     /* Process HPD: */
0181     hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
0182     hpd_int_ctrl   = hdmi_read(hdmi, REG_HDMI_HPD_INT_CTRL);
0183 
0184     if ((hpd_int_ctrl & HDMI_HPD_INT_CTRL_INT_EN) &&
0185             (hpd_int_status & HDMI_HPD_INT_STATUS_INT)) {
0186         bool detected = !!(hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED);
0187 
0188         /* ack & disable (temporarily) HPD events: */
0189         hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL,
0190             HDMI_HPD_INT_CTRL_INT_ACK);
0191 
0192         DBG("status=%04x, ctrl=%04x", hpd_int_status, hpd_int_ctrl);
0193 
0194         /* detect disconnect if we are connected or visa versa: */
0195         hpd_int_ctrl = HDMI_HPD_INT_CTRL_INT_EN;
0196         if (!detected)
0197             hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
0198         hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
0199 
0200         queue_work(hdmi->workq, &hdmi_bridge->hpd_work);
0201     }
0202 }
0203 
0204 static enum drm_connector_status detect_reg(struct hdmi *hdmi)
0205 {
0206     uint32_t hpd_int_status;
0207 
0208     pm_runtime_get_sync(&hdmi->pdev->dev);
0209     enable_hpd_clocks(hdmi, true);
0210 
0211     hpd_int_status = hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS);
0212 
0213     enable_hpd_clocks(hdmi, false);
0214     pm_runtime_put(&hdmi->pdev->dev);
0215 
0216     return (hpd_int_status & HDMI_HPD_INT_STATUS_CABLE_DETECTED) ?
0217             connector_status_connected : connector_status_disconnected;
0218 }
0219 
0220 #define HPD_GPIO_INDEX  2
0221 static enum drm_connector_status detect_gpio(struct hdmi *hdmi)
0222 {
0223     return gpiod_get_value(hdmi->hpd_gpiod) ?
0224             connector_status_connected :
0225             connector_status_disconnected;
0226 }
0227 
0228 enum drm_connector_status msm_hdmi_bridge_detect(
0229         struct drm_bridge *bridge)
0230 {
0231     struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
0232     struct hdmi *hdmi = hdmi_bridge->hdmi;
0233     enum drm_connector_status stat_gpio, stat_reg;
0234     int retry = 20;
0235 
0236     /*
0237      * some platforms may not have hpd gpio. Rely only on the status
0238      * provided by REG_HDMI_HPD_INT_STATUS in this case.
0239      */
0240     if (!hdmi->hpd_gpiod)
0241         return detect_reg(hdmi);
0242 
0243     do {
0244         stat_gpio = detect_gpio(hdmi);
0245         stat_reg  = detect_reg(hdmi);
0246 
0247         if (stat_gpio == stat_reg)
0248             break;
0249 
0250         mdelay(10);
0251     } while (--retry);
0252 
0253     /* the status we get from reading gpio seems to be more reliable,
0254      * so trust that one the most if we didn't manage to get hdmi and
0255      * gpio status to agree:
0256      */
0257     if (stat_gpio != stat_reg) {
0258         DBG("HDMI_HPD_INT_STATUS tells us: %d", stat_reg);
0259         DBG("hpd gpio tells us: %d", stat_gpio);
0260     }
0261 
0262     return stat_gpio;
0263 }