Lines Matching full:hdmi
12 #include <linux/hdmi.h>
509 static int inno_hdmi_find_phy_config(struct inno_hdmi *hdmi,
513 hdmi->variant->phy_configs;
521 DRM_DEV_DEBUG(hdmi->dev, "No phy configuration for pixelclock %lu\n",
527 static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
529 return readl_relaxed(hdmi->regs + (offset) * 0x04);
532 static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
534 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
537 static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
540 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
543 hdmi_writeb(hdmi, offset, temp);
546 static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi, unsigned long long rate)
552 hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
553 hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
556 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
557 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
560 static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
563 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
565 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
568 static void inno_hdmi_standby(struct inno_hdmi *hdmi)
570 inno_hdmi_sys_power(hdmi, false);
572 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
573 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
574 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
575 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
578 static void inno_hdmi_power_up(struct inno_hdmi *hdmi,
582 int ret = inno_hdmi_find_phy_config(hdmi, mpixelclock);
585 phy_config = hdmi->variant->default_phy_config;
586 DRM_DEV_ERROR(hdmi->dev,
590 phy_config = &hdmi->variant->phy_configs[ret];
593 inno_hdmi_sys_power(hdmi, false);
595 hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, phy_config->pre_emphasis);
596 hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->voltage_level_control);
597 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
598 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
599 hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
600 hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
601 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
602 hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
604 inno_hdmi_sys_power(hdmi, true);
607 static void inno_hdmi_init_hw(struct inno_hdmi *hdmi)
612 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
615 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
620 hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
622 inno_hdmi_standby(hdmi);
631 if (hdmi->refclk)
632 inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->refclk));
634 inno_hdmi_i2c_init(hdmi, clk_get_rate(hdmi->pclk));
637 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
643 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
651 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, INFOFRAME_AVI);
660 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
672 hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i, buffer[i]);
682 static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
684 struct drm_connector *connector = &hdmi->connector;
696 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
703 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
705 if (conn_state->hdmi.output_format == HDMI_COLORSPACE_RGB) {
706 if (conn_state->hdmi.is_limited_range) {
714 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
716 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
724 if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
731 if (conn_state->hdmi.output_format == HDMI_COLORSPACE_YUV444) {
741 hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
745 hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
746 hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
753 static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
758 if (hdmi->variant->dev_type == RK3036_HDMI) {
763 regmap_write(hdmi->grf, RK3036_GRF_SOC_CON2, value);
774 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
778 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
779 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
782 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
783 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
786 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
787 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
790 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
791 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
794 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
795 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
798 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
801 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
804 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
806 hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
807 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
808 hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
813 static int inno_hdmi_setup(struct inno_hdmi *hdmi,
816 struct drm_connector *connector = &hdmi->connector;
830 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
833 /* Set HDMI Mode */
834 hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
837 inno_hdmi_config_video_timing(hdmi, &new_crtc_state->adjusted_mode);
839 inno_hdmi_config_video_csc(hdmi);
849 inno_hdmi_i2c_init(hdmi, new_conn_state->hdmi.tmds_char_rate);
852 hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
855 inno_hdmi_power_up(hdmi, new_conn_state->hdmi.tmds_char_rate);
860 static enum drm_mode_status inno_hdmi_display_mode_valid(struct inno_hdmi *hdmi,
875 if (inno_hdmi_find_phy_config(hdmi, mpixelclk) < 0)
878 if (hdmi->refclk) {
879 rounded_refclk = clk_round_rate(hdmi->refclk, mpixelclk);
895 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
897 inno_hdmi_setup(hdmi, state);
903 struct inno_hdmi *hdmi = encoder_to_inno_hdmi(encoder);
905 inno_hdmi_standby(hdmi);
942 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
944 return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
950 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
954 if (!hdmi->ddc)
957 drm_edid = drm_edid_read_ddc(connector, hdmi->ddc);
969 struct inno_hdmi *hdmi = connector_to_inno_hdmi(connector);
971 return inno_hdmi_display_mode_valid(hdmi, mode);
1038 static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
1040 struct drm_encoder *encoder = &hdmi->encoder.encoder;
1041 struct device *dev = hdmi->dev;
1057 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
1059 drm_connector_helper_add(&hdmi->connector,
1061 drmm_connector_hdmi_init(drm, &hdmi->connector,
1062 "Rockchip", "Inno HDMI",
1066 hdmi->ddc,
1070 drm_connector_attach_encoder(&hdmi->connector, encoder);
1075 static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
1077 struct inno_hdmi_i2c *i2c = hdmi->i2c;
1080 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
1084 /* Clear HDMI EDID interrupt flag */
1085 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
1094 struct inno_hdmi *hdmi = dev_id;
1098 if (hdmi->i2c)
1099 ret = inno_hdmi_i2c_irq(hdmi);
1101 interrupt = hdmi_readb(hdmi, HDMI_STATUS);
1103 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
1112 struct inno_hdmi *hdmi = dev_id;
1114 drm_helper_hpd_irq_event(hdmi->connector.dev);
1119 static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
1125 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
1130 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
1135 static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
1145 reinit_completion(&hdmi->i2c->cmp);
1148 hdmi->i2c->segment_addr = msgs->buf[0];
1150 hdmi->i2c->ddc_addr = msgs->buf[0];
1153 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
1156 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
1159 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
1167 struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
1168 struct inno_hdmi_i2c *i2c = hdmi->i2c;
1174 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
1175 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
1178 DRM_DEV_DEBUG(hdmi->dev,
1183 ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
1185 ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
1194 /* Mute HDMI EDID interrupt */
1195 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
1212 static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
1218 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
1227 adap->dev.parent = hdmi->dev;
1228 adap->dev.of_node = hdmi->dev->of_node;
1230 strscpy(adap->name, "Inno HDMI", sizeof(adap->name));
1231 i2c_set_adapdata(adap, hdmi);
1233 ret = devm_i2c_add_adapter(hdmi->dev, adap);
1235 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
1239 hdmi->i2c = i2c;
1241 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
1251 struct inno_hdmi *hdmi;
1256 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1257 if (!hdmi)
1260 hdmi->dev = dev;
1262 variant = of_device_get_match_data(hdmi->dev);
1266 hdmi->variant = variant;
1268 hdmi->regs = devm_platform_ioremap_resource(pdev, 0);
1269 if (IS_ERR(hdmi->regs))
1270 return PTR_ERR(hdmi->regs);
1272 hdmi->pclk = devm_clk_get_enabled(hdmi->dev, "pclk");
1273 if (IS_ERR(hdmi->pclk))
1274 return dev_err_probe(dev, PTR_ERR(hdmi->pclk), "Unable to get HDMI pclk\n");
1276 hdmi->refclk = devm_clk_get_optional_enabled(hdmi->dev, "ref");
1277 if (IS_ERR(hdmi->refclk))
1278 return dev_err_probe(dev, PTR_ERR(hdmi->refclk), "Unable to get HDMI refclk\n");
1280 if (hdmi->variant->dev_type == RK3036_HDMI) {
1281 hdmi->grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
1282 if (IS_ERR(hdmi->grf))
1284 PTR_ERR(hdmi->grf), "Unable to get rockchip,grf\n");
1291 inno_hdmi_init_hw(hdmi);
1293 hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
1294 if (IS_ERR(hdmi->ddc))
1295 return PTR_ERR(hdmi->ddc);
1297 ret = inno_hdmi_register(drm, hdmi);
1301 dev_set_drvdata(dev, hdmi);
1305 dev_name(dev), hdmi);
1311 hdmi->connector.funcs->destroy(&hdmi->connector);
1312 hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
1319 struct inno_hdmi *hdmi = dev_get_drvdata(dev);
1321 hdmi->connector.funcs->destroy(&hdmi->connector);
1322 hdmi->encoder.encoder.funcs->destroy(&hdmi->encoder.encoder);
1353 { .compatible = "rockchip,rk3036-inno-hdmi",
1356 { .compatible = "rockchip,rk3128-inno-hdmi",