18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2013 Red Hat 48c2ecf20Sopenharmony_ci * Author: Rob Clark <robdclark@gmail.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#ifndef __HDMI_CONNECTOR_H__ 88c2ecf20Sopenharmony_ci#define __HDMI_CONNECTOR_H__ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/i2c.h> 118c2ecf20Sopenharmony_ci#include <linux/clk.h> 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 148c2ecf20Sopenharmony_ci#include <linux/gpio/consumer.h> 158c2ecf20Sopenharmony_ci#include <linux/hdmi.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <drm/drm_bridge.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "msm_drv.h" 208c2ecf20Sopenharmony_ci#include "hdmi.xml.h" 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_cistruct hdmi_phy; 238c2ecf20Sopenharmony_cistruct hdmi_platform_config; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct hdmi_audio { 268c2ecf20Sopenharmony_ci bool enabled; 278c2ecf20Sopenharmony_ci struct hdmi_audio_infoframe infoframe; 288c2ecf20Sopenharmony_ci int rate; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistruct hdmi_hdcp_ctrl; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistruct hdmi { 348c2ecf20Sopenharmony_ci struct drm_device *dev; 358c2ecf20Sopenharmony_ci struct platform_device *pdev; 368c2ecf20Sopenharmony_ci struct platform_device *audio_pdev; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci const struct hdmi_platform_config *config; 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci /* audio state: */ 418c2ecf20Sopenharmony_ci struct hdmi_audio audio; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci /* video state: */ 448c2ecf20Sopenharmony_ci bool power_on; 458c2ecf20Sopenharmony_ci unsigned long int pixclock; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci void __iomem *mmio; 488c2ecf20Sopenharmony_ci void __iomem *qfprom_mmio; 498c2ecf20Sopenharmony_ci phys_addr_t mmio_phy_addr; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci struct regulator **hpd_regs; 528c2ecf20Sopenharmony_ci struct regulator **pwr_regs; 538c2ecf20Sopenharmony_ci struct clk **hpd_clks; 548c2ecf20Sopenharmony_ci struct clk **pwr_clks; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci struct gpio_desc *hpd_gpiod; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci struct hdmi_phy *phy; 598c2ecf20Sopenharmony_ci struct device *phy_dev; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci struct i2c_adapter *i2c; 628c2ecf20Sopenharmony_ci struct drm_connector *connector; 638c2ecf20Sopenharmony_ci struct drm_bridge *bridge; 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci /* the encoder we are hooked to (outside of hdmi block) */ 668c2ecf20Sopenharmony_ci struct drm_encoder *encoder; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci bool hdmi_mode; /* are we in hdmi mode? */ 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci int irq; 718c2ecf20Sopenharmony_ci struct workqueue_struct *workq; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci struct hdmi_hdcp_ctrl *hdcp_ctrl; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ci /* 768c2ecf20Sopenharmony_ci * spinlock to protect registers shared by different execution 778c2ecf20Sopenharmony_ci * REG_HDMI_CTRL 788c2ecf20Sopenharmony_ci * REG_HDMI_DDC_ARBITRATION 798c2ecf20Sopenharmony_ci * REG_HDMI_HDCP_INT_CTRL 808c2ecf20Sopenharmony_ci * REG_HDMI_HPD_CTRL 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci spinlock_t reg_lock; 838c2ecf20Sopenharmony_ci}; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci/* platform config data (ie. from DT, or pdata) */ 868c2ecf20Sopenharmony_cistruct hdmi_platform_config { 878c2ecf20Sopenharmony_ci const char *mmio_name; 888c2ecf20Sopenharmony_ci const char *qfprom_mmio_name; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci /* regulators that need to be on for hpd: */ 918c2ecf20Sopenharmony_ci const char **hpd_reg_names; 928c2ecf20Sopenharmony_ci int hpd_reg_cnt; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* regulators that need to be on for screen pwr: */ 958c2ecf20Sopenharmony_ci const char **pwr_reg_names; 968c2ecf20Sopenharmony_ci int pwr_reg_cnt; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* clks that need to be on for hpd: */ 998c2ecf20Sopenharmony_ci const char **hpd_clk_names; 1008c2ecf20Sopenharmony_ci const long unsigned *hpd_freq; 1018c2ecf20Sopenharmony_ci int hpd_clk_cnt; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* clks that need to be on for screen pwr (ie pixel clk): */ 1048c2ecf20Sopenharmony_ci const char **pwr_clk_names; 1058c2ecf20Sopenharmony_ci int pwr_clk_cnt; 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistruct hdmi_bridge { 1098c2ecf20Sopenharmony_ci struct drm_bridge base; 1108c2ecf20Sopenharmony_ci struct hdmi *hdmi; 1118c2ecf20Sopenharmony_ci struct work_struct hpd_work; 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base) 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_civoid msm_hdmi_set_mode(struct hdmi *hdmi, bool power_on); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci msm_writel(data, hdmi->mmio + reg); 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic inline u32 hdmi_read(struct hdmi *hdmi, u32 reg) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci return msm_readl(hdmi->mmio + reg); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic inline u32 hdmi_qfprom_read(struct hdmi *hdmi, u32 reg) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci return msm_readl(hdmi->qfprom_mmio + reg); 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci/* 1338c2ecf20Sopenharmony_ci * hdmi phy: 1348c2ecf20Sopenharmony_ci */ 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cienum hdmi_phy_type { 1378c2ecf20Sopenharmony_ci MSM_HDMI_PHY_8x60, 1388c2ecf20Sopenharmony_ci MSM_HDMI_PHY_8960, 1398c2ecf20Sopenharmony_ci MSM_HDMI_PHY_8x74, 1408c2ecf20Sopenharmony_ci MSM_HDMI_PHY_8996, 1418c2ecf20Sopenharmony_ci MSM_HDMI_PHY_MAX, 1428c2ecf20Sopenharmony_ci}; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistruct hdmi_phy_cfg { 1458c2ecf20Sopenharmony_ci enum hdmi_phy_type type; 1468c2ecf20Sopenharmony_ci void (*powerup)(struct hdmi_phy *phy, unsigned long int pixclock); 1478c2ecf20Sopenharmony_ci void (*powerdown)(struct hdmi_phy *phy); 1488c2ecf20Sopenharmony_ci const char * const *reg_names; 1498c2ecf20Sopenharmony_ci int num_regs; 1508c2ecf20Sopenharmony_ci const char * const *clk_names; 1518c2ecf20Sopenharmony_ci int num_clks; 1528c2ecf20Sopenharmony_ci}; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ciextern const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg; 1558c2ecf20Sopenharmony_ciextern const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg; 1568c2ecf20Sopenharmony_ciextern const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg; 1578c2ecf20Sopenharmony_ciextern const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistruct hdmi_phy { 1608c2ecf20Sopenharmony_ci struct platform_device *pdev; 1618c2ecf20Sopenharmony_ci void __iomem *mmio; 1628c2ecf20Sopenharmony_ci struct hdmi_phy_cfg *cfg; 1638c2ecf20Sopenharmony_ci const struct hdmi_phy_funcs *funcs; 1648c2ecf20Sopenharmony_ci struct regulator **regs; 1658c2ecf20Sopenharmony_ci struct clk **clks; 1668c2ecf20Sopenharmony_ci}; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic inline void hdmi_phy_write(struct hdmi_phy *phy, u32 reg, u32 data) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci msm_writel(data, phy->mmio + reg); 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic inline u32 hdmi_phy_read(struct hdmi_phy *phy, u32 reg) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci return msm_readl(phy->mmio + reg); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ciint msm_hdmi_phy_resource_enable(struct hdmi_phy *phy); 1798c2ecf20Sopenharmony_civoid msm_hdmi_phy_resource_disable(struct hdmi_phy *phy); 1808c2ecf20Sopenharmony_civoid msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock); 1818c2ecf20Sopenharmony_civoid msm_hdmi_phy_powerdown(struct hdmi_phy *phy); 1828c2ecf20Sopenharmony_civoid __init msm_hdmi_phy_driver_register(void); 1838c2ecf20Sopenharmony_civoid __exit msm_hdmi_phy_driver_unregister(void); 1848c2ecf20Sopenharmony_ci 1858c2ecf20Sopenharmony_ci#ifdef CONFIG_COMMON_CLK 1868c2ecf20Sopenharmony_ciint msm_hdmi_pll_8960_init(struct platform_device *pdev); 1878c2ecf20Sopenharmony_ciint msm_hdmi_pll_8996_init(struct platform_device *pdev); 1888c2ecf20Sopenharmony_ci#else 1898c2ecf20Sopenharmony_cistatic inline int msm_hdmi_pll_8960_init(struct platform_device *pdev) 1908c2ecf20Sopenharmony_ci{ 1918c2ecf20Sopenharmony_ci return -ENODEV; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic inline int msm_hdmi_pll_8996_init(struct platform_device *pdev) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci return -ENODEV; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci#endif 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci/* 2018c2ecf20Sopenharmony_ci * audio: 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_ci/* Supported HDMI Audio channels and rates */ 2048c2ecf20Sopenharmony_ci#define MSM_HDMI_AUDIO_CHANNEL_2 0 2058c2ecf20Sopenharmony_ci#define MSM_HDMI_AUDIO_CHANNEL_4 1 2068c2ecf20Sopenharmony_ci#define MSM_HDMI_AUDIO_CHANNEL_6 2 2078c2ecf20Sopenharmony_ci#define MSM_HDMI_AUDIO_CHANNEL_8 3 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_32KHZ 0 2108c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_44_1KHZ 1 2118c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_48KHZ 2 2128c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_88_2KHZ 3 2138c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_96KHZ 4 2148c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_176_4KHZ 5 2158c2ecf20Sopenharmony_ci#define HDMI_SAMPLE_RATE_192KHZ 6 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ciint msm_hdmi_audio_update(struct hdmi *hdmi); 2188c2ecf20Sopenharmony_ciint msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled, 2198c2ecf20Sopenharmony_ci uint32_t num_of_channels, uint32_t channel_allocation, 2208c2ecf20Sopenharmony_ci uint32_t level_shift, bool down_mix); 2218c2ecf20Sopenharmony_civoid msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/* 2258c2ecf20Sopenharmony_ci * hdmi bridge: 2268c2ecf20Sopenharmony_ci */ 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistruct drm_bridge *msm_hdmi_bridge_init(struct hdmi *hdmi); 2298c2ecf20Sopenharmony_civoid msm_hdmi_bridge_destroy(struct drm_bridge *bridge); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_civoid msm_hdmi_hpd_irq(struct drm_bridge *bridge); 2328c2ecf20Sopenharmony_cienum drm_connector_status msm_hdmi_bridge_detect( 2338c2ecf20Sopenharmony_ci struct drm_bridge *bridge); 2348c2ecf20Sopenharmony_ciint msm_hdmi_hpd_enable(struct drm_bridge *bridge); 2358c2ecf20Sopenharmony_civoid msm_hdmi_hpd_disable(struct hdmi_bridge *hdmi_bridge); 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/* 2388c2ecf20Sopenharmony_ci * i2c adapter for ddc: 2398c2ecf20Sopenharmony_ci */ 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_civoid msm_hdmi_i2c_irq(struct i2c_adapter *i2c); 2428c2ecf20Sopenharmony_civoid msm_hdmi_i2c_destroy(struct i2c_adapter *i2c); 2438c2ecf20Sopenharmony_cistruct i2c_adapter *msm_hdmi_i2c_init(struct hdmi *hdmi); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci/* 2468c2ecf20Sopenharmony_ci * hdcp 2478c2ecf20Sopenharmony_ci */ 2488c2ecf20Sopenharmony_ci#ifdef CONFIG_DRM_MSM_HDMI_HDCP 2498c2ecf20Sopenharmony_cistruct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi); 2508c2ecf20Sopenharmony_civoid msm_hdmi_hdcp_destroy(struct hdmi *hdmi); 2518c2ecf20Sopenharmony_civoid msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl); 2528c2ecf20Sopenharmony_civoid msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl); 2538c2ecf20Sopenharmony_civoid msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl); 2548c2ecf20Sopenharmony_ci#else 2558c2ecf20Sopenharmony_cistatic inline struct hdmi_hdcp_ctrl *msm_hdmi_hdcp_init(struct hdmi *hdmi) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci return ERR_PTR(-ENXIO); 2588c2ecf20Sopenharmony_ci} 2598c2ecf20Sopenharmony_cistatic inline void msm_hdmi_hdcp_destroy(struct hdmi *hdmi) {} 2608c2ecf20Sopenharmony_cistatic inline void msm_hdmi_hdcp_on(struct hdmi_hdcp_ctrl *hdcp_ctrl) {} 2618c2ecf20Sopenharmony_cistatic inline void msm_hdmi_hdcp_off(struct hdmi_hdcp_ctrl *hdcp_ctrl) {} 2628c2ecf20Sopenharmony_cistatic inline void msm_hdmi_hdcp_irq(struct hdmi_hdcp_ctrl *hdcp_ctrl) {} 2638c2ecf20Sopenharmony_ci#endif 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci#endif /* __HDMI_CONNECTOR_H__ */ 266